[状压dp] Jzoj P1768 炮兵阵地
题解
- 一看m<=10,当然上状压啊
- 对于放置一支炮兵部队,它只会影响向上下左右各两格的位置
- 那么我们就可以枚举前两行和当前行的状态,再判断其是否可以行
- 那这样的话,复杂度就是O(n*2^3m)会超时
- 可以在每个枚举后进行剪枝,而不是所有枚举完三个后才判断其是否可行
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 using namespace std; 5 int n,m,a[101][11],k[101],f[101][101][101],ans,x; 6 void dfs(int x,int y) 7 { 8 if (x<=m) dfs(x+1,y),dfs(x+1,y^(1<<(x-1))); 9 else if ((y&(y<<1))==0&&(y&(y<<2))==0) k[++k[0]]=y; 10 } 11 int get(int x,int y) 12 { 13 int k=0; 14 for (int i=1;i<=m;i++) 15 if (a[y][i]==1) 16 { 17 if ((x&(1<<(i-1)))!=0) k++; 18 } 19 else if ((x&(1<<(i-1)))!=0) return -1; 20 return k; 21 } 22 bool pd(int x,int y) { return (x&y)==0; } 23 int main() 24 { 25 scanf("%d%d",&n,&m); 26 for (int i=1;i<=n;i++) 27 { 28 scanf("\n"); 29 char ch; 30 for (int j=1;j<=m;j++) 31 { 32 scanf("%c",&ch); 33 if (ch=='H') a[i][j]=0; else a[i][j]=1; 34 } 35 } 36 dfs(1,0); 37 for (int i=1;i<=n;i++) 38 for (int j=1;j<=k[0];j++) 39 if ((x=get(k[j],i))!=-1) 40 for (int i1=1;i1<=k[0];i1++) 41 if (pd(k[j],k[i1])) 42 for (int j1=1;j1<=k[0];j1++) 43 if (pd(k[j],k[j1])) 44 f[i][j][i1]=max(f[i-1][i1][j1]+x,f[i][j][i1]); 45 for (int i=1;i<=k[0];i++) 46 for (int j=1;j<=k[0];j++) 47 ans=max(ans,f[n][i][j]); 48 printf("%d",ans); 49 return 0; 50 }