leetcode 2132. 用邮票贴满网格图

这题写了好久,一开始掉一个坑里面没出来。

我一开始想的是列举邮贴的左上角贴在每个格子的情况,提前计算出前缀和判断是否可贴,可贴的话就把贴的那块区域全部都赋值为已访问。往后遍历的时候,已访问过的就不再考虑它作为左上角的情况,这样应该不会超时。并没有想到采用延迟更新。

结果样例都没过,然后对着样例发现没有考虑每个格子作为其他三个角的情况,然后补成了每个格子作为四个角的情况,结果样例过了,交上去过了60+,wa了。

然后静下心来再想了想,想到了正解。写第一个解法浪费了太多时间。

怎么说呢,也不知道为什么,都已经想到前缀和了,咋一开始就没想到前缀和搭配的延迟更新呢?咳!可能是因为之前没有写过二维的延迟更新吧,所以反应没有那么快。

想到了延迟更新就好办了,不清楚一维数组延迟更新的方法的自行搜索吧,这里给出二维数组延迟更新的方法:

比方说要给阴影区域每个格子都加1,那么需要给以下四个格子标记,最后延迟更新完事。

代码如下:

typedef long long ll;
class Solution {
public:
    bool possibleToStamp(vector<vector<int>>& grid, int stampHeight, int stampWidth) {
        int n=grid.size();
        int m=grid[0].size();
        vector<vector<int>> A;
        vector<vector<int>> B;
        vector<vector<int>> C;
        for(int i=0;i<n;i++) A.push_back(vector<int>()),B.push_back(vector<int>()),C.push_back(vector<int>());
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            {
                A[i].push_back(grid[i][j]^1);
                if(i==0&&j!=0) A[i][j]+=A[i][j-1];
                else if(i!=0&&j==0) A[i][j]+=A[i-1][j];
                else if(i!=0&&j!=0) A[i][j]+=(A[i-1][j]+A[i][j-1]-A[i-1][j-1]);
                B[i].push_back(grid[i][j]);
                C[i].push_back(0);
            }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(B[i][j]==0)
                {
                    int x=i+stampHeight-1,y=j+stampWidth-1;
                    if(x<n&&y<m)
                    {
                        int sum=A[x][y];
                        if(i==0&&j!=0) sum-=A[x][j-1];
                        else if(i!=0&&j==0) sum-=A[i-1][y];
                        else if(i!=0&&j!=0) sum-=(A[i-1][y]+A[x][j-1]-A[i-1][j-1]);
                        if(sum==stampHeight*stampWidth)
                        {
                            C[i][j]+=1;
                            if(x+1<n&&y+1>=m) C[x+1][j]-=1;
                            else if(x+1>=n&&y+1<m) C[i][y+1]-=1;
                            else if(x+1<n&&y+1<m) C[x+1][j]-=1,C[i][y+1]-=1,C[x+1][y+1]+=1;
                        }
                    }
                }
            }
        }
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            {
                if(i==0&&j!=0) C[i][j]+=C[i][j-1];
                else if(i!=0&&j==0) C[i][j]+=C[i-1][j];
                else if(i!=0&&j!=0) C[i][j]+=(C[i-1][j]+C[i][j-1]-C[i-1][j-1]);
            }

        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                if(grid[i][j]==0&&C[i][j]==0) return false;
        return true;
        
    }
};

最后想了一段时间才想出我第一个解法的问题:

对于下图的情况,按照我第一个解法,那么中间那块区域是不可能被覆盖的,但实际上是可以被填充的。就错了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值