链接:http://poj.org/problem?id=1185 #include<stdio.h> #define N 100 #define M 10 #define Max(a,b) a>b?a:b int dp[2][N][N]; //滚动数组 表示 当前合法状态 及上次合法状态 char map[M]; //每一行地图 struct node{ int army; //部队人数 int status; //布局时炮兵安排 , 用二进制 表示 1 代表 炮兵, 0 代表 无 }leg[N]; //存储单行合法的炮兵布局 int legNum ; //单行合法炮兵布局数 int leg_m; //当每行长度为m 时,最大的合法二进制数 int Graph[N]; //地图每一行的存储,二进制 ,1代表山地,0代表平原 void GetLeg() { int i,temp; int n=(1<<11); legNum = 0; leg[legNum].army=0; leg[legNum].status=0; for(i=1;i<n;i++){ temp=i; if(((temp<<1)&temp)||((temp<<2)&temp)) //不满足两炮兵互相攻击的状态 continue; leg[++legNum].army=0; leg[legNum].status=i; while(temp){ if(temp&1)leg[legNum].army++; temp=temp>>1; } } } //二分的思想查找 int Get(int x){ int left=0,right=legNum,mid; int ans=0; while(left<=right){ mid=((left+right)>>1); if(leg[mid].status>x){ ans = mid; right = mid -1; } else left = mid +1; } return ans; } int main() { int max,n,m,i,j,k,Bin_map,t; GetLeg(); while(scanf("%d%d",&n,&m)!=EOF){ for(i=0;i<n;i++){ scanf("%s",map); Bin_map=0 ; //把地图转化为二进制表示 for(j=0;j<m;j++){ Bin_map=(Bin_map<<1) + (map[j]=='P'?0:1); } Graph[i]=Bin_map; } leg_m = Get((1<<m)-1); for(i=0;i<2;i++) for(j=0;j<leg_m;j++) for(k=0;k<leg_m;k++) dp[i][j][k]=0; /初始化第一行 for(i=0;i<leg_m;i++){ if((leg[i].status&Graph[0])==0) dp[0][i][0]=leg[i].army; } if(n>=2){ /初始化第二行 for(i=0;i<leg_m;i++){ if((leg[i].status&Graph[1])==0){ //排除山地 for(j=0;j<leg_m;j++){ if((leg[j].status&leg[i].status)==0)//两行没有冲突 dp[1][i][j]=dp[0][j][0]+leg[i].army; } } } 做 2 -> n 行 for(t=2;t<n;t++){ for(i=0;i<leg_m;i++){ if((leg[i].status&Graph[t])==0){ //排除山地 for(j=0;j<leg_m;j++){ max=0; if((leg[i].status&leg[j].status)==0){//与上层没有冲突 for(k=0;k<leg_m;k++){ if((leg[i].status&leg[k].status)==0){//与上上层没有冲突 max=Max(dp[(t-1)&1][j][k]+leg[i].army,max); } } } dp[t&1][i][j]=max; } } } } }//if(n!=1) max=0; t=(n-1)&1; for(i=0;i<leg_m;i++) for(j=0;j<leg_m;j++) max=Max(dp[t][i][j],max); printf("%d/n",max); } return 0; }