NOI2001 炮兵陣地 計蒜客習題 灌溉機器人

狀壓dp入門題 昨天調好久了結果zz把判斷行內相交的函數寫錯沒調出來  位運算優先級搞錯了)

點擊打開鏈接

#include<iostream>
#include<cstdio>
#include<cctype>
#include<cmath>
//狀態:dp[i][j][k]表示當前在第i行 i行狀態編號爲j i-1行狀態編號爲k的最大格子數
//答案即爲dp[n][i][j] 中枚舉i和j找到的最大值
using namespace std;
const int maxn=110;
const int maxm=10;
int map[maxn];               //每一行的合法狀態並集
int dp[maxn][70][70];//需要保存當前行與上一行的狀態
int state[100];  //60種狀態集合
int sum[100];    //60種狀態對應的可擺放機器人個數
bool fit(int x,int y){return (x|y)==y;}  //集合x能放入y
bool ok(int x){ return !(x&(x>>1)||x&(x>>2));}    //行內不相交 
bool not_i(int x,int y){return !(x&y);}
int count(int x){
    int s=0;
    while(x){
        s+=(x&1);
        x>>=1;
    }
    return s;
}
int main(){
    int n,m;
    cin>>n>>m;
    //可選格子(P)記爲1 不可選記爲0
    for(int i=1;i<=n;++i)
        for(int j=0;j<m;++j)
        {
            char c=getchar();
            while(!isalpha(c)) c=getchar();        
            if(c=='P') map[i]|=(1<<j);    //存儲每行的可用格子
        }
    //預處理出60種狀態
    int cnt=0;
    for(int i=0;i<(1<<m);i++){
        if(ok(i)){  //合法的行內狀態
            state[++cnt]=i;
            if(cnt>60)
            {printf("%d\n",cnt);return 0;}
            sum[cnt]=count(i);
            //out<<sum[cnt]<<endl;
        }
    }
    //對第一行和第二行需要自行判斷
    for(int i=1;i<=cnt;i++)
    {
        if(fit(state[i],map[1])) 
            dp[1][i][0]=sum[i]; 
       //cout<<sum[i]<<endl;
    }       
    for(int i=1;i<=cnt;i++){
        if(!fit(state[i],map[2])) continue; //找出一種含於map[2]的狀態
        for(int j=1;j<=cnt;j++)
        {
            if(!fit(state[j],map[1])) continue;//找第一行的合法狀態
            if(not_i(state[i],state[j])) //判斷第一行與第二行是否相交
            {
                dp[2][i][j]=sum[i]+sum[j];
                //cout<<dp[2][i][j]<<endl;
            }
        }
    }
    int res=0;
    
    for(int i=3;i<=n;i++)
    {
        for(int j=1;j<=cnt;j++){
            if(!fit(state[j],map[i])) continue;//找到第i行的某一狀態
            for(int k=1;k<=cnt;k++)//上一行的狀態
            {
                if(!fit(state[k],map[i-1])||!not_i(state[j],state[k])) continue;//確保state[i]能放進map[i-1]
                for(int l=1;l<=cnt;l++){
                    if(!fit(state[l],map[i-2])||!not_i(state[k],state[l])||!not_i(state[j],state[l])) continue;
                    dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+sum[j]);
                   // cout<<dp[i][j][k]<<endl;  
                }
            }
        }
    }
    for(int i=1;i<=cnt;i++){
        for(int j=1;j<=cnt;j++)
        {
            res=max(res,dp[n][i][j]);
        }
    }
    cout<<res<<endl;
    return 0;
}

 

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