刚刚学习状态压缩,看到这样的问题真的有些不知所措
所以看了大神的题解,得到了这种题的解题思路
这个题的状态就是每一行的炮兵阵地摆放不能相邻,或者仅隔一个位置
找出每一行的状态数最多是sum=60个左右(当列数为10时)
每一行的状态都受起那两行的状态影响,所以不难得出算法的时间复杂度为n*sum^3
/**
初学状态压缩
题目:poj 1185 炮兵阵地
解决方法:状态压缩,滚动数组
*/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
char c[105][15];
int a[105]; //记录每行状态
int state[70],cor=0;
int num[70];//记录每个状态的炮兵数
int dp[70][70][2];
int fun(int num){
int ans=0;
while(num){
if(num%2)ans++;
num/=2;
}
return ans;
}
void Init(){
//不含相邻的和仅隔一个位置的炮兵阵地
for(int i=0;i<(1<<10);i++)
if((i&(i<<1))==0 && (i&(i<<2))==0 &&
(i&(i>>1))==0 && (i&(i>>2))==0){
state[cor]=i;
num[cor++]=fun(i);
}
}
int main(){
Init();
int n,m;
while(~scanf("%d%d",&n,&m)){
for(int i=0;i<n;i++){
scanf("%s",c[i]);
a[i]=0;
for(int j=0;j<m;j++){
a[i]<<=1;
if(c[i][j]=='H') a[i]|=1;
}
}
memset(dp,-1,sizeof(dp));
dp[0][0][0]=0;
int now=0,top=1<<m;
for(int i=0;i<n;i++){//依次遍历每一行更新每一个状态值
for(int j=0;j<cor&&state[j]<top;j++)
for(int k=0;k<cor&&state[k]<top;k++)
if(dp[j][k][now]!=-1)
for(int t=0;t<cor&&state[t]<top;t++)
if((a[i]&state[t])==0&&
(state[t]&state[j])==0&&
(state[t]&state[k])==0)
dp[k][t][now^1]=max(dp[k][t][now^1],
dp[j][k][now]+num[t]);
now^=1;
}
int ans=0;
for(int i=0;i<cor&&state[i]<top;i++)
for(int j=0;j<cor&&state[j]<top;j++)
ans=max(dp[i][j][now],ans);
printf("%d\n",ans);
}
return 0;
}