1 条题解

  • 0
    @ 2026-6-5 13:16:38

    相当巧妙的解法(考虑到正常人看代码想半天可能也不知道为啥,特发此篇)

    思路

    注意到H,W3000H,W\leq3000,暴力枚举每一个点,定义状态fi,jf_{i,j}为以(i,j)(i,j)为右下角的没有洞正方形的数量,转移方程如下:

    f[i][j]=min(f[i1][j1],f[i1][j],f[i][j1])+1f[i][j]=min({f[i-1][j-1],f[i-1][j],f[i][j-1]})+1

    为啥了?

    这一个+1+1很好理解,就是他自己一个点。前面的minmin一大串其实就是他左上方最大的没有洞正方形。不难发现fi,jf_{i,j}也表示一个点左上角最大没有洞正方形的边长,给一个点的左上,左,右的ff取最小值,就是这个点左上方的最大没有洞正方形。

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=3100;
    int n,m,k,a[N][N];
    long long f[N][N],ans;
    int main()
    {
    	scanf("%d%d%d",&n,&m,&k);
    	for(int i=1,x,y;i<=k;i++)
    	{
    		scanf("%d%d",&x,&y);
    		a[x][y]=1;
    	}
    	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
    	{
    		if(a[i][j])continue;
    		f[i][j]=min({f[i-1][j-1],f[i-1][j],f[i][j-1]})+1;
    		ans+=f[i][j];
    	}
    	printf("%lld\n",ans);
    	return 0;
    }
    

    代码好短~~~

    • 1

    信息

    ID
    8895
    时间
    2000ms
    内存
    1024MiB
    难度
    6
    标签
    递交数
    24
    已通过
    12
    上传者