以后做比赛前一定补好睡眠,没有精神A不动题目……,最后一题的题意到2H才发现看错了,原来是要求曼哈顿距离等于2的而不是小于等于2的……,调了半天样例都输出1……。最后只AC了2题,第一个和最后一个,第二个怎么想怎么是爆搜,是不是爆搜?
最后一题排兵布阵是比较经典的状压DP,看群里还有用点独立集做的,还有用插头DP做的?ORZ。
做法跟POJ 1185炮兵阵地,这道经典状压DP神似,连题目都神似。所以具体转移方程也基本一样,需要枚举前两行的状态。具体细节不明白的可以先去搜poj 1185的解题报告。
题目虽然给的时间很多,但是比赛怕超时就先预处理了所有当前行可行的状态。判断当前行k,和k-2行是否兼容跟炮兵阵地的处理方式一样,直接相与。处理k跟k-1行略有不同,是把k-1行的状态搓一个位(其实就是乘2,除2)相与,看这两个结果有没有不等于0的。其他都跟炮兵一样。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <set> 2 #include <list> 3 #include <queue> 4 #include <stack> 5 #include <cmath> 6 #include <ctime> 7 #include <vector> 8 #include <bitset> 9 #include <cstdio> 10 #include <string> 11 #include <numeric> 12 #include <cstring> 13 #include <cstdlib> 14 #include <iostream> 15 #include <algorithm> 16 #include <functional> 17 using namespace std; 18 typedef long long ll; 19 #define Exp 1e-8 20 #define inf 0x7fffffff 21 #define read freopen("in.txt","r",stdin) 22 #define write freopen("out.txt","w",stdout) 23 #define maxn 200 24 int n,m,top; 25 int map[105][12],con[maxn][maxn],con2[maxn][maxn]; 26 int state[maxn][2],vm[105],dp[105][maxn][maxn]; 27 int max(int a,int b) 28 { 29 if(a>b)return a; 30 return b; 31 } 32 void prt(int i) 33 { 34 int t=i;while(t)printf("%d",t%2),t>>=1;puts(""); 35 } 36 bool check(int a,int b)//判断当前行的状态能否放入地图中 37 { 38 if(((~b)&a))return false; 39 return true; 40 } 41 void init()//预处理一行能够放士兵的状态 42 { 43 int i,j; 44 memset(state,0,sizeof(state)); 45 top=0; 46 for(i=0;i<(1<<10)-1;++i) 47 { 48 if((i&(i<<2)))continue; 49 state[top][0]=i;//0存放状态,1统计个数 50 for(j=i;j;j-=j&(-j))state[top][1]++; 51 ++top;//prt(state[top-1][0]); 52 } 53 for(i=0;i<top;++i)for(j=0;j<top;++j)//con[i][j]表示当前行跟上一行状态为i,j是否能共存 54 con[i][j]=!(state[i][0]&state[j][0]); 55 for(i=0;i<top;++i)for(j=0;j<top;++j)//con[i][j]表示当前行跟上二行状态为i,j是否能共存 56 { 57 int t1=state[i][0]&(state[j][0]<<1); 58 int t2=state[i][0]&(state[j][0]>>1); 59 con2[i][j]=!(t1|t2); 60 } 61 } 62 int main() 63 { 64 //read; 65 init(); 66 int i,j,k,s; 67 while(~scanf("%d%d",&n,&m)) 68 { 69 memset(vm,0,sizeof(vm)); 70 memset(map,0,sizeof(map)); 71 memset(dp,0,sizeof(dp)); 72 for(i=0;i<n;++i) 73 { 74 for(j=0;j<m;++j) 75 { 76 scanf("%d",&map[i][j]); 77 vm[i]=(vm[i]+map[i][j])<<1; 78 } 79 vm[i]>>=1;//地图信息状态压缩 80 } 81 for(i=0;i<top;++i) 82 { 83 if(check(state[i][0],vm[0])==0)continue; 84 for(j=0;j<top;j++)dp[0][i][j]=state[i][1]; 85 } 86 for(i=0;i<top;++i) 87 { 88 if(check(state[i][0],vm[1])==0)continue; 89 for(j=0;j<top;j++) 90 { 91 if(check(state[j][0],vm[0])==0)continue; 92 if(con2[i][j]==0)continue; 93 dp[1][i][j]=max(dp[1][i][j],dp[0][j][0]+state[i][1]); 94 } 95 } 96 for(s=2;s<n;++s) 97 for(i=0;i<top;++i) 98 { 99 if(check(state[i][0],vm[s])==0)continue; 100 for(j=0;j<top;++j) 101 { 102 if(check(state[j][0],vm[s-1])==0)continue; 103 if(con2[i][j]==0)continue; 104 for(k=0;k<top;++k) 105 { 106 if(check(state[k][0],vm[s-2])==0)continue; 107 if(con2[j][k]==0||con[i][k]==0)continue; 108 dp[s][i][j]=max(dp[s][i][j],state[i][1]+dp[s-1][j][k]); 109 } 110 } 111 } 112 int ans=0; 113 for(i=0;i<top;++i)for(j=0;j<top;++j)ans=max(ans,dp[n-1][i][j]) ; 114 printf("%d\n",ans); 115 } 116 return 0; 117 }