思维状压dp—— 2020 联想杯 M
Posted zsben991126
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了思维状压dp—— 2020 联想杯 M相关的知识,希望对你有一定的参考价值。
这个状压还要输出方案实在是太ex了
第 i 行放完了水后,能新种下的甘蔗数量取决于 i − 1 行和 i − 2 行 的状态
令 dp【i,j】 表示放完前 i 行且最后两行状态为 j 时最多能种下的数量
我们在第 i 行放水有可能能使 i − 1 行的某个格子能够放上甘蔗了, 但如果不知道 i − 2 行的状态的话是没办法确定该格子是否已经被 放过了的
决策就是枚举第 i 行水是如何放的
#include "bits/stdc++.h" #define hhh cerr<<"hhh"<<endl #define see(x) cerr<<(#x)<<‘=‘<<(x)<<endl using namespace std; typedef long long ll; typedef pair<int,int> pr; inline int read() {int x=0,f=1;char c=getchar();while(c!=‘-‘&&(c<‘0‘||c>‘9‘))c=getchar();if(c==‘-‘)f=-1,c=getchar();while(c>=‘0‘&&c<=‘9‘)x=x*10+c-‘0‘,c=getchar();return f*x;} const int maxn = 3e5+7; const int inf = 0x3f3f3f3f; const int mod = 1e9+7; int n, m; int dp[33][256][256], from[33][256][256]; char mp[33][10]; string res[33]; int main() { n=read(), m=read(); for(int i=0; i<n; ++i) scanf("%s", mp[i]); memset(dp,-1,sizeof(dp)); memset(from,-1,sizeof(from)); if(n==1) { int ans=-1, state=-1; for(int s=0; s<1<<m; ++s) { int tmp=0; for(int j=0; j<m; ++j) { if(!(s>>j&1)) { tmp++; if(mp[0][j]==‘.‘) { int f=0; if(j>0&&(s>>(j-1)&1)) f=1; else if(j<m-1&&(s>>(j+1)&1)) f=1; if(!f) { tmp=-1; break; } } } else if(mp[0][j]==‘#‘) { tmp=-1; break; } } if(tmp<0) continue; if(tmp>ans) ans=tmp, state=s; } for(int i=0; i<m; ++i) { if(state>>i&1) printf("O"); else if(mp[0][i]==‘#‘) printf("#"); else printf("X"); } puts(""); return 0; } for(int s=0; s<1<<m; ++s) { for(int s1=0; s1<1<<m; ++s1) { int tmp=0; for(int j=0; j<m; ++j) { if(!(s>>j&1)) tmp++; else if(mp[1][j]==‘#‘) { tmp=-1; break; } } if(tmp<0) continue; for(int j=0; j<m; ++j) { if(!(s1>>j&1)) { tmp++; if(mp[0][j]==‘.‘) { int f=0; if(j>0&&s1>>(j-1)&1) f=1; else if(j<m-1&&s1>>(j+1)&1) f=1; else if(s>>j&1) f=1; if(!f) { tmp=-1; break; } } } else if(mp[0][j]==‘#‘) { tmp=-1; break; } } dp[1][s][s1]=tmp; } } for(int i=2; i<n; ++i) { for(int s=0; s<1<<m; ++s) { int tmp=0; for(int j=0; j<m; ++j) { if(!(s>>j&1)) tmp++; else if(mp[i][j]==‘#‘) { tmp=-1; break; } } if(tmp<0) continue; for(int s1=0; s1<1<<m; ++s1) { int f=1; for(int j=0; j<m; ++j) { if(!(s1>>j&1)) ; else if(mp[i-1][j]==‘#‘) { f=0; break; } } if(!f) continue; int mx=-1, state=-1; for(int s2=0; s2<1<<m; ++s2) if(dp[i-1][s1][s2]>=0) { int f1=1; for(int j=0; j<m; ++j) { if(!(s1>>j&1)&&mp[i-1][j]==‘.‘) { int f=0; if(j>0&&(s1>>(j-1)&1)) f=1; else if(j<m-1&&(s1>>(j+1)&1)) f=1; else if(s>>j&1) f=1; else if(s2>>j&1) f=1; if(!f) { f1=0; break; } } } if(f1&&dp[i-1][s1][s2]>mx) { mx=dp[i-1][s1][s2]; state=s2; } } if(mx>=0) { dp[i][s][s1]=tmp+mx; from[i][s][s1]=state; } } } } int mx=-1, state=-1, state1=-1; for(int s=0; s<1<<m; ++s) { for(int s1=0; s1<1<<m; ++s1) if(dp[n-1][s][s1]>=0) { int f1=1; for(int j=0; j<m; ++j) { if(!(s>>j&1)&&mp[n-1][j]==‘.‘) { int f=0; if(j>0&&(s>>(j-1)&1)) f=1; else if(j<m-1&&(s>>(j+1)&1)) f=1; else if(s1>>j&1) f=1; if(!f) { f1=0; break; } } } if(f1&&dp[n-1][s][s1]>mx) { mx=dp[n-1][s][s1]; state=s; state1=s1; } } } int s=state, s1=state1; for(int i=n-1; i>1; --i) { for(int j=0; j<m; ++j) { if(s>>j&1) res[i]+=‘O‘; else if(mp[i][j]==‘#‘) res[i]+=‘#‘; else res[i]+=‘X‘; } int s2=from[i][s][s1]; s=s1, s1=s2; } for(int j=0; j<m; ++j) { if(s>>j&1) res[1]+=‘O‘; else if(mp[1][j]==‘#‘) res[1]+=‘#‘; else res[1]+=‘X‘; } s=s1; for(int j=0; j<m; ++j) { if(s>>j&1) res[0]+=‘O‘; else if(mp[0][j]==‘#‘) res[0]+=‘#‘; else res[0]+=‘X‘; } for(int i=0; i<n; ++i) cout<<res[i]<<endl; }
以上是关于思维状压dp—— 2020 联想杯 M的主要内容,如果未能解决你的问题,请参考以下文章
[状压dp] aw3494. 国际象棋(状压dp+第12届蓝桥杯CB组)