• 差分约束


    题目

    给一个m * n的矩阵,现在每次可以选择以元素ai为第一行第一列的大小为a * b的矩阵,矩阵中的每个元素都将-ai。选取的矩阵不能超过m*n的范围之外。现在问是否能将矩阵中的元素全部变为0.

    解法

    由于选取的a * b矩阵必须在原矩阵之中,那么第1行,第1列的元素肯定是要作为起始元素的。因此,我们从上到下,从左到右依此进行消除,看最终能否消除成功。时间复杂度为O(n * m * a * b)。
    上面的算法m * n是不可避免的 ,我们可以用二维差分来优化区间修改操作。原始算法我们需要O(a * b)的时间复杂度进行修改,现在我们可以只用O(1)的时间复杂度进行修改。
    二维差分
    diff[i][j]=diff[i][j]-diff[i-1][j]-diff[i][j-1]+diff[i-1][j-1]
    修改时:若对矩形(x1,y1,x2,y2)进行区间加tmp,则等效于mp[x1][y1]+=tmp ; mp[x2+1][y2+1]+=tmp ; mp[x1][y2+1]-=tmp; mp[x2+1][y1]-=tmp
    代码如下:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int mp[1010][1010];
    int diff[1010][1010];
    int main()
    {
        int T,n,m,a,b;
        scanf("%d",&T);
        for(int cas=1;cas<=T;cas++){
           scanf("%d%d%d%d",&n,&m,&a,&b); 
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    scanf("%d",&mp[i][j]);
                    diff[i][j]=mp[i][j]-mp[i-1][j]-mp[i][j-1]+mp[i-1][j-1];
                }  
            }
            bool flag=1;
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    int tmp=diff[i][j];
                    //cout<<tmp<<endl;
                    if(!tmp)  continue;
                    else if(tmp<0)
                    {
                        flag=0;
                        break;
                    }
                    else if(i+a-1<=n&&j+b-1<=m)
                    {
                        diff[i][j]-=tmp;
                        diff[i+a][j+b]-=tmp;
                        diff[i][j+b]+=tmp;
                        diff[i+a][j]+=tmp;
                    }
                    else{
                        flag=0;
                        break;
                    }
                }
            }
            if(!flag)
                cout<<"QAQ"<<endl;
            else
                cout<<"^_^"<<endl;
        }
    }
    
  • 相关阅读:
    上传项目到github上
    app widget设置bitmap时,无作用
    Android Studio 启动app 白屏
    android sqlite 数据库中使用的类型
    android 解决华为系列手机调试时不能打印Logcat日志信息
    android 自定义滚动条图标
    检测邮箱
    js检测是否存在中文
    表单的checkbox选中和取消
    javascript
  • 原文地址:https://www.cnblogs.com/flightless/p/13948561.html
Copyright © 2020-2023  润新知