Codeforces(D. 505)状压DP
程序员文章站
2022-07-01 10:50:16
...
亏我上上个星期还写过状压DP专题,1个多小时硬是没反应过来这题是个状压,一直还当成一个普通二维DP去想状态表示,宛如个智障一样
代码:
#include <bits/stdc++.h>
#define ll long long
#define IOS std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
template<class T> inline void read(T &x){
x=0; register char c=getchar(); register bool f=0;
while(!isdigit(c))f^=c=='-',c=getchar();
while(isdigit(c))x=x*10+c-'0',c=getchar(); if(f)x=-x;
}
using namespace std;
ll n,m,inf=999999999999999999;
string s[1000006];
int a[1000006][17];
ll d[1000006][17];
ll u[10],v[10];
ll query(ll x,ll y)
{
for(int i=1;i<=m;i++){u[i]=0;v[i]=0;}
ll cnt1=0,cnt2=0,flag=1;
while(x>0)
{u[++cnt1]=x%2;x/=2;}
while(y>0)
{v[++cnt2]=y%2;y/=2;}
for(int i=2;i<=m;i++)
{
ll sum=u[i]+u[i-1]+v[i]+v[i-1];
if(sum%2==0){flag=0;break;}
}
return flag;
}
ll consume(ll x,ll y)
{
ll r=0;
for(int i=m;i>=1;i--)
{
if(y%2==a[x][i]){y/=2;}
else{y/=2;r++;}
}
return r;
}
int main()
{
IOS
cin>>n>>m;
for(int i=0;i<n;i++)
{cin>>s[i];}
if(n>=4&&m>=4){cout<<"-1"<<endl;return 0;}
if(n==1||m==1){cout<<"0"<<endl;return 0;}
if(n>=m)
{
for(int i=0;i<n;i++)
{
for(int j=0 ;j<m;j++)
{a[i+1][j+1]=s[i][j]-'0';}
}
}
else
{
int x=1,y=1;
for(int j=m-1;j>=0;j--)
{
for(int i=0;i<n;i++)
{
a[x][y]=s[i][j]-'0';
y++;
if(y>n){y=1;x++;}
}
}
swap(n,m);
}
for(int i=2;i<=n;i++)
{
for(int j=0;j<(1<<m);j++)
{d[i][j]=inf;}
}
for(int j=0;j<(1<<m);j++)
{
ll y=j;
for(int i=m;i>=1;i--)
{
if(y%2==a[1][i]){y/=2;}
else{y/=2;d[1][j]++;}
}
}
for(int i=2;i<=n;i++)
{
for(int k=0;k<(1<<m);k++)//枚举上一层状态
{
for(int j=0;j<(1<<m);j++)//枚举当前状态
{
if(query(j,k)!=1){continue;}
ll cost=consume(i,j);
d[i][j]=min(d[i][j],d[i-1][k]+cost);
}
}
}
ll ans=inf;
for(int j=0;j<(1<<m);j++)
{ans=min(d[n][j],ans);}
cout<<ans<<endl;
return 0;
}
下一篇: wifi p2p学习