状态压缩,$dp$,预处理。
设$dp[i][j]$为前$i-1$行填满,第$i$行为状态$j$的最小需要$1$种类的数量。预处理好每种状态能推出哪些状态,并且记录下所需花费就可以了。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-6; void File() { freopen("D:\in.txt","r",stdin); freopen("D:\out.txt","w",stdout); } template <class T> inline void read(T &x) { char c = getchar(); x = 0; while(!isdigit(c)) c = getchar(); while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } } struct X { int nx,cost; }q[100000]; int n,c,cnt; vector<int>v[40]; char s[1010][10]; int st[1010]; int dp[1005][35]; int check(int s,int pos) { if(s&(1<<pos)) return 1; return 0; } void dfs(int S,int no,int p,int nx,int co) { if(p==5) { q[cnt].nx=nx; q[cnt].cost=co; v[S].push_back(cnt); cnt++; return ; } if(check(no,p)) dfs(S,no,p+1,nx,co); //1 if(check(no,p)==0) dfs(S,no+(1<<p),p+1,nx,co+1); //2 if(p>0&&check(no,p)==0&&check(nx,p)==0&&check(nx,p-1)==0) dfs(S,no+(1<<p),p+1,nx+(1<<p)+(1<<(p-1)),co); //3 if(p+1<=4&&check(no,p)==0&&check(no,p+1)==0&&check(nx,p)==0&&check(nx,p+1)==0) dfs(S,no+(1<<p)+(1<<(p+1)),p+2,nx+(1<<p)+(1<<(p+1)),co); //4 if(p+1<=4&&check(no,p)==0&&check(no,p+1)==0) dfs(S,no+(1<<p)+(1<<(p+1)),p+2,nx,co); //5 if(check(no,p)==0&&check(nx,p)==0) dfs(S,no+(1<<p),p+1,nx+(1<<p),co); //6 if(p+1<=4&&check(no,p)==0&&check(nx,p)==0&&check(nx,p+1)==0) dfs(S,no+(1<<p),p+1,nx+(1<<p)+(1<<(p+1)),co); //7 if(p+1<=4&&check(no,p)==0&&check(no,p+1)==0&&check(nx,p+1)==0) dfs(S,no+(1<<p)+(1<<(p+1)),p+2,nx+(1<<(p+1)),co); //8 if(p+1<=4&&check(no,p)==0&&check(no,p+1)==0&&check(nx,p)==0) dfs(S,no+(1<<p)+(1<<(p+1)),p+2,nx+(1<<p),co); } void init() { cnt=0; for(int i=0;i<(1<<5);i++) dfs(i,i,0,0,0); } int main() { init(); while(~scanf("%d%d",&n,&c)) { for(int i=0;i<n;i++) scanf("%s",s[i]); for(int i=0;i<n;i++) { st[i]=0; for(int j=0;j<5;j++) { int x=s[i][j]-'0'; st[i]=st[i]+x*(1<<j); } } st[n]=0; memset(dp,-1,sizeof dp); dp[0][st[0]]=0; for(int i=0;i<n;i++) { for(int j=0;j<32;j++) { if(dp[i][j]==-1) continue; //printf("******** "); for(int t=0;t<v[j].size();t++) { int id=v[j][t]; if(c-dp[i][j]<q[id].cost) continue; if(st[i+1]&q[id].nx) continue; if(dp[i+1][(q[id].nx)|st[i+1]]==-1) dp[i+1][(q[id].nx)|st[i+1]]=dp[i][j]+q[id].cost; else dp[i+1][(q[id].nx)|st[i+1]]=min(dp[i+1][(q[id].nx)|st[i+1]],dp[i][j]+q[id].cost); } } } if(dp[n][0]!=-1&&dp[n][0]<=c) printf("YES "); else printf("NO "); } return 0; }