poj 1185
地址:http://poj.org/problem?id=1185
题意:中文……
mark:经典的状态压缩dp。第一次写,在网上看别人解题报告看了好多,百度一下就有很多。
推荐一个解释很详细的解题报告http://apps.hi.baidu.com/share/detail/14572384
wa了好多次。特别是match函数那,有很多a,b为0的时候的临界情况。
ps:别人的代码不一定是正确的,我找了一篇ac代码,然后比对数据,结果发现他的数据不对。囧……
代码:
#include <stdio.h> #include <string.h> #define N 61 int dp[2][N][N]; int n,m,len; int sum[N],num[N];//sum[]代表1的个数,num[]代表10进制数 int max(int a, int b) {return a > b ? a : b;} void build() { int i,tem; len = 0; for(i = 0; i < (1 << m); i++) { tem = i; if(((tem << 1) & i) || ((tem << 2) & i)) continue; num[len] = tem; sum[len] = 0; while(tem) { sum[len] += (tem & 1); tem = (tem >> 1); } len++; } } int match(int a, int b) { int i; if(!a && !b) return 1; //wa的地方!!! if(!b) return 0; //wa的地方!!! while(a || b) { if(!(b & 1)) if(a & 1) return 0; a = (a >> 1); b = (b >> 1); } return 1; } int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); char a[110][11]; int num2[110];//每一行代表的10进制数 int i,j,k,p; int max1,ans; while(~scanf("%d%d", &n, &m)) { build(); for(i = 1; i <= n; i++) scanf("%s", a[i]); for(i = 1; i <= n; i++) { num2[i] = (a[i][0] == 'P'); for(j = 1; j < m; j++) num2[i] = (num2[i] << 1) + (a[i][j] == 'P'); } memset(dp, 0, sizeof(dp)); for(j = 0; j < len; j++) { if(match(num[j], num2[1])) for(k = 0; k < len; k++) dp[1][j][k] = sum[j]; } for(j = 0; j < len; j++) { if(match(num[j], num2[2])) for(k = 0; k < len; k++) if(!(num[j] & num[k])) dp[0][j][k] = dp[1][k][0]+sum[j]; } for(i = 3; i <= n; i++) { for(j = 0; j < len; j++) { if(match(num[j], num2[i])) { for(k = 0; k < len; k++) { if(!(num[j] & num[k])) { max1 = 0; for(p = 0; p < len; p++) { if(!(num[j] & num[p])) max1 = max(max1, dp[!(i%2)][k][p]); } dp[i%2][j][k] = max1+sum[j]; } } } } } ans = 0; for(i = 0; i < len; i++) for(j = 0; j < len; j++) ans = max(ans, dp[n%2][i][j]); printf("%d\n", ans); } return 0; }