poj 1185 炮兵阵地
链接:点我
又是去年的题,拿到就忘了
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 #define max(a,b) (a) > (b) ? (a) : (b) 5 6 int N,M; 7 char map[110][20],num[110],top; 8 int stk[70],cur[110]; 9 int dp[110][70][70]; 10 11 inline bool ok(int x){ //判断该状态是否合法,即不存在相邻的1之间的距离小于3的 12 if(x&(x<<1)) return 0; 13 if(x&(x<<2)) return 0; 14 return 1; 15 } 16 //找到所有可能的合法状态,最多60种 17 inline void jinit() 18 { 19 top=0; 20 int i,total=1<<N; 21 for(i=0;i<total;i++) if(ok(i)) stk[++top]=i; 22 } 23 //判断状态x是否与第k行匹配 24 inline bool fit(int x,int k) 25 { 26 if(cur[k]&x) return 0; 27 return 1; 28 } 29 //数一个整型数x的二进制中1的个数(用于初始化) 30 inline int jcount(int x) 31 { 32 int cnt=0; 33 while(x) 34 { 35 cnt++; 36 x&=(x-1); 37 } 38 return cnt; 39 } 40 41 int main(){ 42 while(scanf("%d%d",&M,&N) != EOF){ 43 if(N == 0 && M == 0)break; 44 jinit(); 45 for(int i = 1; i <= M; ++i)scanf("%s",map[i]+1); 46 for(int i = 1; i <= M; ++i) 47 for(int j = 1; j <= N; ++j){ 48 cur[i]=0; 49 for(j=1;j<=N;j++){ 50 if(map[i][j]=='H')cur[i]+=(1<<(j-1)); 51 } 52 } 53 memset(dp,-1,sizeof(dp)); 54 55 //初始化第一行状态 56 for(int i = 1;i <= top;i++){ 57 num[i]=jcount(stk[i]); 58 if(fit(stk[i],1)) 59 dp[1][1][i]=num[i]; 60 } 61 int i,t,j,k; 62 for(i = 2;i <= M;i++){ 63 for(t = 1;t <= top;t++){ 64 if(!fit(stk[t],i)) continue; 65 for(j = 1;j <= top;j++) 66 { 67 if(stk[t]&stk[j])continue; 68 for(k = 1;k <= top;k++) 69 { 70 if(stk[t]&stk[k])continue; 71 if(dp[i-1][j][k]==-1)continue; 72 dp[i][k][t] =max(dp[i][k][t],dp[i-1][j][k]+num[t]); 73 } 74 } 75 } 76 } 77 int ans = 0; 78 for(j = 1; j <= top; ++j) 79 for(k = 1; k <= top; ++k) 80 ans = max(ans,dp[M][j][k]); 81 printf("%d\n",ans); 82 } 83 return 0; 84 }