码迷,mamicode.com
首页 > 其他好文 > 详细

【思维】状压dp—— 2020 联想杯 M

时间:2020-06-02 19:12:37      阅读:78      评论:0      收藏:0      [点我收藏+]

标签:ace   names   minus   namespace   状压dp   +=   bit   ++   color   

这个状压还要输出方案实在是太ex了

第 i 行放完了水后,能新种下的甘蔗数量取决于 i − 1 行和 i − 2 行 的状态

令 dp【i,j】 表示放完前 i 行且最后两行状态为 j 时最多能种下的数量

我们在第 i 行放水有可能能使 i − 1 行的某个格子能够放上甘蔗了, 但如果不知道 i − 2 行的状态的话是没办法确定该格子是否已经被 放过了的

 

决策就是枚举第 i 行水是如何放的

#include "bits/stdc++.h"
#define hhh cerr<<"hhh"<<endl
#define see(x) cerr<<(#x)<<‘=‘<<(x)<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {int x=0,f=1;char c=getchar();while(c!=-&&(c<0||c>9))c=getchar();if(c==-)f=-1,c=getchar();while(c>=0&&c<=9)x=x*10+c-0,c=getchar();return f*x;}

const int maxn = 3e5+7;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;

int n, m;
int dp[33][256][256], from[33][256][256];
char mp[33][10];
string res[33];

int main() {
    n=read(), m=read();
    for(int i=0; i<n; ++i) scanf("%s", mp[i]);
    memset(dp,-1,sizeof(dp));
    memset(from,-1,sizeof(from));
    if(n==1) {
        int ans=-1, state=-1;
        for(int s=0; s<1<<m; ++s) {
            int tmp=0;
            for(int j=0; j<m; ++j) {
                if(!(s>>j&1)) {
                    tmp++;
                    if(mp[0][j]==.) {
                        int f=0;
                        if(j>0&&(s>>(j-1)&1)) f=1;
                        else if(j<m-1&&(s>>(j+1)&1)) f=1;
                        if(!f) { tmp=-1; break; }
                    }
                }
                else if(mp[0][j]==#) { tmp=-1; break; }
            }
            if(tmp<0) continue;
            if(tmp>ans) ans=tmp, state=s;
        }
        for(int i=0; i<m; ++i) {
            if(state>>i&1) printf("O");
            else if(mp[0][i]==#) printf("#");
            else printf("X");
        }
        puts("");
        return 0;
    }
    for(int s=0; s<1<<m; ++s) {
        for(int s1=0; s1<1<<m; ++s1)  {
            int tmp=0;
            for(int j=0; j<m; ++j) {
                if(!(s>>j&1)) tmp++;
                else if(mp[1][j]==#) { tmp=-1; break; }
            }
            if(tmp<0) continue;
            for(int j=0; j<m; ++j) {
                if(!(s1>>j&1)) {
                    tmp++;
                    if(mp[0][j]==.) {
                        int f=0;
                        if(j>0&&s1>>(j-1)&1) f=1;
                        else if(j<m-1&&s1>>(j+1)&1) f=1;
                        else if(s>>j&1) f=1;
                        if(!f) { tmp=-1; break; }
                    }
                }
                else if(mp[0][j]==#) { tmp=-1; break; }
            }
            dp[1][s][s1]=tmp;
        }
    }
    for(int i=2; i<n; ++i) {
        for(int s=0; s<1<<m; ++s) {
            int tmp=0;
            for(int j=0; j<m; ++j) {
                if(!(s>>j&1)) tmp++;
                else if(mp[i][j]==#) { tmp=-1; break; }
            }
            if(tmp<0) continue;
            for(int s1=0; s1<1<<m; ++s1) {
                int f=1;
                for(int j=0; j<m; ++j) {
                    if(!(s1>>j&1)) ;
                    else if(mp[i-1][j]==#) { f=0; break; }
                }
                if(!f) continue;
                int mx=-1, state=-1;
                for(int s2=0; s2<1<<m; ++s2) if(dp[i-1][s1][s2]>=0) {
                    int f1=1;
                    for(int j=0; j<m; ++j) {
                        if(!(s1>>j&1)&&mp[i-1][j]==.) {
                            int f=0;
                            if(j>0&&(s1>>(j-1)&1)) f=1;
                            else if(j<m-1&&(s1>>(j+1)&1)) f=1;
                            else if(s>>j&1) f=1;
                            else if(s2>>j&1) f=1;
                            if(!f) { f1=0; break; }
                        }
                    }
                    if(f1&&dp[i-1][s1][s2]>mx) {
                        mx=dp[i-1][s1][s2];
                        state=s2;
                    }
                }
                if(mx>=0) {
                    dp[i][s][s1]=tmp+mx;
                    from[i][s][s1]=state;
                }
            }
        }
    }
    int mx=-1, state=-1, state1=-1;
    for(int s=0; s<1<<m; ++s) {
        for(int s1=0; s1<1<<m; ++s1) if(dp[n-1][s][s1]>=0) {
            int f1=1;
            for(int j=0; j<m; ++j) {
                if(!(s>>j&1)&&mp[n-1][j]==.) {
                    int f=0;
                    if(j>0&&(s>>(j-1)&1)) f=1;
                    else if(j<m-1&&(s>>(j+1)&1)) f=1;
                    else if(s1>>j&1) f=1;
                    if(!f) { f1=0; break; }
                }
            }
            if(f1&&dp[n-1][s][s1]>mx) {
                mx=dp[n-1][s][s1];
                state=s;
                state1=s1;
            }
        }
    }
    int s=state, s1=state1;
    for(int i=n-1; i>1; --i) {
        for(int j=0; j<m; ++j) {
            if(s>>j&1) res[i]+=O;
            else if(mp[i][j]==#) res[i]+=#;
            else res[i]+=X;
        }
        int s2=from[i][s][s1];
        s=s1, s1=s2;
    }
    for(int j=0; j<m; ++j) {
        if(s>>j&1) res[1]+=O;
        else if(mp[1][j]==#) res[1]+=#;
        else res[1]+=X;
    }
    s=s1;
    for(int j=0; j<m; ++j) {
        if(s>>j&1) res[0]+=O;
        else if(mp[0][j]==#) res[0]+=#;
        else res[0]+=X;
    }
    for(int i=0; i<n; ++i) cout<<res[i]<<endl;
}

 

【思维】状压dp—— 2020 联想杯 M

标签:ace   names   minus   namespace   状压dp   +=   bit   ++   color   

原文地址:https://www.cnblogs.com/zsben991126/p/13032641.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!