码迷,mamicode.com
首页 > 其他好文 > 详细

CF1391D 505(状压dp+思维)

时间:2020-09-03 16:39:40      阅读:36      评论:0      收藏:0      [点我收藏+]

标签:cin   ++   const   std   type   最小值   技术   lse   air   

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

进一步发现,题目要求正方形矩阵的边长为偶数,并且里面的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

 

CF1391D 505(状压dp+思维)

标签:cin   ++   const   std   type   最小值   技术   lse   air   

原文地址:https://www.cnblogs.com/ctyakwf/p/13552880.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!