http://poj.org/problem?id=1185
参考博客:http://poj.org/problem?id=1185
大神博客已经讲的很清楚了,注意存状态的时候是从1开始的,所以初始化的时候也是dp[1][1][state],从0开始的话,状态就是dp[1][0][state]了.
dp[i][j][k]表示第i行状态为k第i-1行状态为j时的方案数.
dp[i][j][k]=max(dp[i][j][k],dp[i-1][t][j]+num[k]); (num[k]为k状态中1的个数)
边界条件:dp[1][1][i]=num[i],状态i可以满足第一行的条件。
还有就是为什么每一行最多只有60种状态,poj题目讨论里面有人给出了枚举的代码。
1 #include <iostream> 2 using namespace std; 3 bool isok( int c ) { 4 return !(c&(c<<1)||c&(c<<2));//同一行中不能有相邻的1距离小于3 5 } 6 int main() { 7 int count=0; 8 for( int i=0; i<1024; i++ ) 9 count += isok(i); 10 cout<<count<<endl; 11 return 0; 12 }
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <vector> 5 #include <cstring> 6 #include <string> 7 #include <algorithm> 8 #include <string> 9 #include <set> 10 #include <functional> 11 #include <numeric> 12 #include <sstream> 13 #include <stack> 14 //#include <map> 15 #include <queue> 16 #include <deque> 17 //#pragma comment(linker, "/STACK:102400000,102400000") 18 #define CL(arr, val) memset(arr, val, sizeof(arr)) 19 20 #define ll long long 21 #define INF 0x7f7f7f7f 22 #define lc l,m,rt<<1 23 #define rc m + 1,r,rt<<1|1 24 #define pi acos(-1.0) 25 26 #define L(x) (x) << 1 27 #define R(x) (x) << 1 | 1 28 #define MID(l, r) (l + r) >> 1 29 #define Min(x, y) (x) < (y) ? (x) : (y) 30 #define Max(x, y) (x) < (y) ? (y) : (x) 31 #define E(x) (1 << (x)) 32 #define iabs(x) (x) < 0 ? -(x) : (x) 33 #define OUT(x) printf("%I64d\n", x) 34 #define lowbit(x) (x)&(-x) 35 #define Read() freopen("a.txt", "r", stdin) 36 #define Write() freopen("b.txt", "w", stdout); 37 #define maxn 110 38 #define maxv 5010 39 #define mod 1000000000 40 using namespace std; 41 int n,m; 42 char map[110][20],num[110],top; 43 int stk[70],cur[110]; 44 int dp[110][70][70]; 45 46 inline bool ok(int x) //判断该状态是否合法,即同一行不存在相邻1之间的距离小于3的 47 { 48 if(x&(x<<1)||x&(x<<2)) return 0; 49 return 1; 50 } 51 inline void jnite() //找到所有可能合法的状态 52 { 53 top=0; 54 int total=1<<m; 55 for(int i=0;i<total;i++) 56 if(ok(i)) stk[++top]=i; 57 } 58 59 inline bool fit(int x,int k) //判断状态x是否与第k行匹配 60 { 61 if(cur[k]&x) return 0; 62 return 1; 63 } 64 inline int jcount(int x) //计算一个整型数x的二进制中1的个数(用于初始化) 65 { 66 int cnt=0; 67 while(x) 68 { 69 cnt++; 70 x&=(x-1); //很精炼,每次都会与掉一个1 71 } 72 return cnt; 73 } 74 int main() 75 { 76 //Read(); 77 while(~scanf("%d%d",&n,&m)) 78 { 79 if(n==0&&m==0) break; 80 jnite(); 81 for(int i=1;i<=n;i++) scanf("%s",map[i]+1); 82 for(int i=1;i<=n;i++) 83 { 84 cur[i]=0; 85 for(int j=1;j<=m;j++) 86 { 87 if(map[i][j]=='H') cur[i]+=(1<<(j-1)); 88 } 89 //printf("%d\n",cur[i]); 90 } 91 memset(dp,0,sizeof(dp)); 92 for(int i=1;i<=top;i++) //初始化第一行 93 { 94 num[i]=jcount(stk[i]); 95 //printf("%d\n",num[i]); 96 if(fit(stk[i],1)) dp[1][1][i]=num[i]; 97 } 98 for(int i=2;i<=n;i++) { 99 for(int t=1;t<=top;t++) { 100 if(!fit(stk[t],i)) continue;//第i行是否冲突 101 for(int j=1;j<=top;j++) { 102 if(stk[t]&stk[j]) continue;//第i行和第i-2行是否冲突 103 for(int k=1;k<=top;k++) { 104 if(stk[t]&stk[k]) continue;//第i行和第i-1行是否冲突 105 dp[i][k][t]=max(dp[i][k][t],dp[i-1][j][k]+num[t]); 106 // printf("%d\n",dp[i][k][t]); 107 } 108 } 109 } 110 } 111 int ans=0; //得到最大值 112 for(int i=1;i<=top;i++) 113 for(int j=1;j<=top;j++) 114 ans=max(ans,dp[n][i][j]); 115 printf("%d\n",ans); 116 } 117 return 0; 118 }