poj 1185 炮兵陣地

poj 1185 炮兵陣地

剛剛學習狀態壓縮,看到這樣的問題真的有些不知所措

所以看了大神的題解,得到了這種題的解題思路

這個題的狀態就是每一行的炮兵陣地擺放不能相鄰,或者僅隔一個位置

找出每一行的狀態數最多是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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章