剛剛學習狀態壓縮,看到這樣的問題真的有些不知所措
所以看了大神的題解,得到了這種題的解題思路
這個題的狀態就是每一行的炮兵陣地擺放不能相鄰,或者僅隔一個位置
找出每一行的狀態數最多是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;
}