Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 22810 | Accepted: 8830 |
Description
Input
Output
Sample Input
5 4 PHPP PPHH PPPP PHPP PHHP
Sample Output
6
思路:
按层数来dp,如果用 dp[i][j][k] 来表示在第 i 行,状态为 j ,i-1行状态为 k 时的状态,那么有转移方程
dp[i][j][k] = max(dp[i][j][k],dp[i-1][k][l] +num[i]);
枚举 i(层数),j(当前层状态),k(上一层状态),l(上上层状态)就可以来进行转移了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m,a; int map[105],dp[2][65][65],num[65],s[65]; int getnum(int x) //用来获取x状态中有多少个1 { int ans = 0; for(int i = 0;i < 10;i++) { if(x & (1<<i)) ans ++; } return ans; } void init() //预处理出最极限情况下可能用到的状态 { a = 0; memset(num,0,sizeof(num)); //a记录了一共有多少个可用状态 for(int i = 0;i < (1<<10);i++) { int i1 = (i>>1); int i2 = (i>>2); if(!(i1 & i) && !(i2 & i)) { s[a] = i; //如果出现了合法状态,就放入s中存储起来 num[a++] = getnum(i); } } } int main() { init();int i,j,k,l;char c; while(scanf("%d%d",&n,&m)!=EOF) { if(n == 0 && m == 0) { cout << 0 << endl; continue; } memset(map,0,sizeof(map)); memset(dp,0,sizeof(dp)); for(i = 0;i < n;i++) { for(j = 0;j < m;j++) { cin >> c; if(c == 'H') map[i] = map[i] | (1<<j); //存图,将‘H’认为是 1 ,即会冲突的点。将一个字符串状态压缩成一个数 } } int now = 0;int res = 0; //滚动数组标记初始为0 for(i = 0;i < a;i++) { if(s[i] >= (1<<m)) break; //如果s[i]这个状态已经超过了当前这组样例的最大状态,则退出 if(!(map[0]&s[i])) { dp[now][i][0] = num[i]; //如果第0行和s[i]状态相 & 为0,则可以处理 dp[now][i][0] res = max(res,dp[now][i][0]); } } if(n == 1) { cout << res << endl; continue; } now ^= 1; for(i = 0;i < a;i++) { if(s[i] >= (1<<m)) break; //如果s[i]这个状态已经超过了当前这组样例的最大状态,则退出 if(map[1]&s[i]) continue; //如果当前状态和图相冲突,continue; for(j = 0;j < a;j++) { if(s[j] >= (1<<m)) break; if(s[i]&s[j]) continue; //如果当前层和上一层相冲突,continue; dp[now][i][j] = max(dp[now][i][j],dp[now^1][j][0] + num[i]); res = max(res,dp[now][i][j]); } } now ^= 1; if(n == 2) { cout << res << endl; continue; } for(l = 2;l < n;l++) { for(i = 0;i < a;i++) { if(s[i] >= (1<<m)) break; if(map[l]&s[i]) continue; for(j = 0;j < a;j++) { if(s[j] >= (1<<m)) break; if(map[l-1]&s[j]) continue; if(s[i]&s[j]) continue; for( k = 0;k < a;k++) { if(s[k] >= (1<<m)) break; if(map[l-2]&s[k]) continue; if((s[i]&s[k]) || (s[j]&s[k])) continue; dp[now][i][j] = max(dp[now][i][j],dp[now^1][j][k] + num[i]); res = max(res,dp[now][i][j]); } } } now ^= 1; } printf("%d\n",res); } return 0; }