状态压缩dp。
一开始想开个dp[2][1024][1024]的数组,显然开不下,而且也会超时。
因此把状态对应放在另外一个数组s里。
map[i]表示用二进制表示第i行的地势情况,1是高地,0是平原。
用dp[i][j][k]表示第i行,达到状态s[j],且i-1行的状态是s[k]的最优解。
状态转移方程为 dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][p]+cnt[j]);
满足状态转移方程的条件是 s[j]&map[i]==0,s[j]&s[k]==0,s[j]&s[p]==0,且dp[i-1][k][p]存在。
//Memory:228K //Time:422ms #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m; int map[110]; int dp[2][110][110]; int s[110],scnt,cnt[110]; void DFS(int dta,int dep) { bool ok=1; if(10==dep) { s[scnt++]=dta; return; } if(dep) { if((1<<(dep-1))&dta) ok=0; if(dep>1) { if((1<<(dep-2))&dta) ok=0; } } if(ok) DFS(dta|(1<<dep),dep+1); DFS(dta,dep+1); } void init() { DFS(0,0); sort(s,s+scnt); s[scnt]=0x3f3f3f3f; for(int i=0;i<scnt;++i) { cnt[i]=0; for(int j=0;j<10;++j) if((1<<j)&s[i]) ++cnt[i]; } } int main() { init(); char str[12]; int hehe; int now,before; int ans; while(scanf("%d%d",&n,&m)==2) { memset(map,0,sizeof map); memset(dp,-1,sizeof dp); dp[0][0][0]=0; for(int i=1;i<=n;++i) { scanf("%s",str); for(int j=0;j<m;++j) if(str[j]=='H') map[i]|=(1<<(m-j-1)); } hehe=1<<m; for(int i=1;i<=n;++i) { now=i&1; before=now?0:1; for(int j=0;s[j]<hehe;++j) { if(s[j]&map[i]) continue; for(int k=0;s[k]<hehe;++k) { if(s[j]&s[k]) continue; dp[now][j][k]=0; for(int p=0;s[p]<hehe;++p) { if(s[j]&s[p]||dp[before][k][p]==-1) continue; dp[now][j][k]=max(dp[now][j][k],dp[before][k][p]+cnt[j]); } } } } ans=0; for(int i=0;s[i]<hehe;++i) { for(int j=0;s[j]<hehe;++j) ans=max(ans,dp[now][i][j]); } printf("%d\n",ans); } }