zoukankan      html  css  js  c++  java
  • CF1391D 505(状压dp+思维)

    观察到这个数据范围,显然不可能真的存这么大的邻接矩阵。

    进一步发现,题目要求正方形矩阵的边长为偶数,并且里面的1为奇数

    这启发了我们,因为边长为4的一定要用边长为2的拼接起来,这样边长为4的里面一定是偶数个1

    因此直接特判掉n>=4的答案

    剩下只有n==2,和n==3。

    对于n==2,我们发现因为每列只能是奇偶奇偶,或者是偶奇偶奇。因此我们就判断这两种情况取一个最小值

    对于n==3,可以发现这是经典的网格图状压,也就是玉米田问题,因为种类只有8,我们先计算不冲突的情况,之后对于枚举每一列,求出合法状态

    最终的答案就是每种状态取min

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    typedef pair<int,pll> plll;
    const int N=5e5+10;
    const int mod=1e9+7;
    char s[5][N];
    int f[N][16];
    vector<int> g[N];
    //判断是否成立
    bool check(int a,int b){
        int a1=(a>>0)&1,b1=(b>>0)&1;
        int a2=(a>>1)&1,b2=(b>>1)&1;
        int a3=(a>>2)&1,b3=(b>>2)&1;
        if((a1+a2+b1+b2)%2==0)
        return false;
        if((a2+a3+b2+b3)%2==0)
        return false;
        return true;
    }
    //计算交换代价
    int cal(int a,int b){
        int a1=s[1][a],b1=(b>>0)&1;
        int a2=s[2][a],b2=(b>>1)&1;
        int a3=s[3][a],b3=(b>>2)&1;
        int ans=0;
        if(a1!=b1)
            ans++;
        if(a2!=b2)
            ans++;
        if(a3!=b3)
            ans++;
        return ans;
    }
    int main(){
        ios::sync_with_stdio(false);
        int n,m;
        cin>>n>>m;
        int i,j;
        if(n==1){
            cout<<0<<endl;
        }
        else if(n>=4){
            cout<<-1<<endl;
        }
        else{
            int i,j;
            for(i=1;i<=n;i++){
                for(j=1;j<=m;j++){
                    char c;
                    cin>>c;
                    s[i][j]=c-'0';
                }
            }
            if(n==2){
                int ans1=0,ans2=0;
                for(i=1;i<=m;i++){
                    int tmp=i&1;
                    if(s[1][i]^s[2][i]!=tmp)
                    ans1++;
                }
                for(i=1;i<=m;i++){
                    int tmp=(i+1)&1;
                    if(s[1][i]^s[2][i]!=tmp)
                        ans2++;
                }
                cout<<min(ans1,ans2)<<endl;
            }
            else{
                for(i=0;i<8;i++){
                    for(j=0;j<8;j++){
                        if(check(i,j))
                            g[i].push_back(j);
                    }
                }
                for(i=0;i<8;i++){
                    f[1][i]=cal(1,i);
                }
                for(i=2;i<=m;i++){
                    for(j=0;j<8;j++){
                        f[i][j]=1e9;
                        for(auto x:g[j]){
                            f[i][j]=min(f[i][j],f[i-1][x]+cal(i,j));
                        }
                    }
                }
                int ans=1e9;
                for(i=0;i<8;i++){
                    ans=min(ans,f[m][i]);
                }
                cout<<ans<<endl;
            }
        }
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    双线性过滤
    textureView
    cubemap
    selfshadow
    cbuffer padding
    异常
    Python深浅拷贝
    数据类型分类
    集合类型内置方法
    字典数据类型内置方法
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13552880.html
Copyright © 2011-2022 走看看