Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 16463 | Accepted: 6266 |
Description
Input
Output
Sample Input
5 4 PHPP PPHH PPPP PHPP PHHP
Sample Output
6
1. 把行看成是一个整体,每一种摆放代表着一种状态,r-2, r-1 行的状态决定着 r 行的状态;
2. 本题状态比较稀疏,所以提前处理下炮兵的摆放无意是比较好的选择,由于没两个炮兵之间至少相距为 2,利用这个把每一行的炮兵可能摆放情况存放起来;
3. dp[r][i][j] 表示第 r 行的状态为 i 且第 r-1 行的状态为 j 时,所能摆放的最大炮兵数量,同时还需要枚举 r-2 行的炮兵摆放情况;
4. 最终有状态转移方程: dp[r][i][j] = max(dp[r][i][j], dp[r-1][j][k] + men[i]); 并且要求 dp[r-1][j][k] 存在,且 r 行能保证能摆放 i 状态;
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<vector> using namespace std; int n,m; typedef long long ll; int dp[102][111][111]; int g[111],state[111],man[221],cnt; bool ok(int x) { if(x&(x>>1))return 0;if(x&(x<<1))return 0; if(x&(x<<2))return 0;if(x&(x>>2))return 0; return 1; } int Count(int x) { int sum=0; while(x) { x=x&(x-1); sum++; } return sum; } void get(int ed) { cnt=0; for(int i=0;i<ed;i++) { if(ok(i)) { state[cnt]=i; man[cnt++]=Count(i); } } } char ch[22]; int main() { while(scanf("%d%d",&n,&m)!=EOF&&n) { int i,j,k;char c; memset(g,0,sizeof g);getchar(); for(int i=0;i<n;i++) { gets(ch);g[i]=0; for(int j=0;j<m;j++) { //cin>>c; if(ch[j]=='H')g[i]=g[i]|(1<<j); } //cout<<g[i]<<' '; } memset(dp,-1,sizeof dp); get((1<<m)); for(int i=0;i<cnt;i++) { if(g[0]&state[i])continue; dp[0][i][0]=man[i]; } //cout<<cnt<<endl;//for(int i=0;i<cnt;i++)cout<<man[i]<<' ';cout<<endl; for(int r=1;r<n;r++) { for(int i=0;i<cnt;i++) { if(g[r]&state[i])continue; for(int j=0;j<cnt;j++) { if(state[i]&state[j])continue; if(state[j]&g[r-1])continue; for(int k=0;k<cnt;k++) { if((state[k]&state[i])||(state[k]&state[j]))continue; if(dp[r-1][j][k]!=-1) { dp[r][i][j]=max(dp[r][i][j],dp[r-1][j][k]+man[i]); } } } } } int ans=0; for(int i=0;i<cnt;i++) for(int j=0;j<cnt;j++) ans=max(ans,dp[n-1][i][j]); cout<<ans<<endl; } }