UCF Local Programming Contest 2015 H. Reach for the Stars(状压dp)

https://nanti.jisuanke.com/t/43393

题意:

给出的图案,用十字的盖章,最少需要盖几次。盖章必须整个盖到图案上

解析:

在这里插入图片描述

对于第i行放置十字的情况,前面的行能影响的区域为红色区域。也就是14个格子。

对于第i行,有7个位置可以填十字。由于左右两个格子是否为空直接影响两边的十字能否填,所以有5个十字。

d p [ i ] [ s 1 ] [ s 2 ] dp[i][s1][s2] 表示填完第i行,第i行的7个位置的状态为s1,第i+1行的7个位置的状态为s2的最少十字数量。

从上一行转移时,枚举中间的5个十字,i-1行为s1,i行为s2,i+1行为s3。要求s1与地图中的相同。s2,s3可以是地图子集。

而14个格子由于下面行一定比上面行少,所以枚举子集复杂度为 3 7 3^7

最大复杂度为 7 3 7 2 7 7 7*3^7*2^7*7

代码:

/*
 *  Author : Jk_Chen
 *    Date : 2020-02-26-13.32.30
 */
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
#define debug(x) cerr<<#x<<" = "<<x<<'\n'
const LL mod=1e9+7;
const int maxn=1e5+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/

char x[12][12];
bool Map[12][12];
int val[12];
int dp[12][1<<7][1<<7];

bool isSon(int fa,int son){
    return (fa&son)==son;
}

int main(){
    int _=rd,cas=0;
    while(_--){
        cas++;
        int n=rd,m=rd;
        rep(i,1,n)scanf("%s",x[i]+1);
        rep(i,1,n){
            rep(j,1,m){
                if(x[i][j]=='#')Map[i][j]=1;
                else Map[i][j]=0;
            }
            val[i]=0;
            rep(j,2,m-1){
                if(Map[i][j])val[i]|=1<<j-2;
            }
        }
        if(n<2||m<2){
            int ct=0;
            rep(i,1,n)rep(j,1,m)if(x[i][j]=='#')ct++;
            if(ct){
                printf("Image #%d: impossible\n\n",cas);
                continue;
            }
            else{
                printf("Image #%d: 0\n\n",cas);
                continue;
            }
        }
        if(x[1][1]=='#'||x[1][m]=='#'||x[n][1]=='#'||x[n][m]=='#'){
            printf("Image #%d: impossible\n\n",cas);
            continue;
        }
        mmm(dp,-1);
        dp[1][0][0]=0;
        int MS=(1<<m-2)-1;
        rep(i,2,n-1){
            rep(s1,0,MS){
                for(int s2=s1;s2!=-1;s2=(s2?((s2-1)&s1):-1)){
                    if(dp[i-1][s1][s2]==-1){
                        continue;
                    }

                    rep(now,0,MS){
                        bool fl=0,fr=0;
                        if(now&1)fl=1;
                        if(now&(1<<m-3))fr=1;
                        if(Map[i][1]!=fl)continue;
                        if(Map[i][m]!=fr)continue;
                        int S1=s1,S2=s2,S3=0;
                        int cnt=0;
                        rep(b,0,m-3){
                            if(now&(1<<b)){
                                S1|=(1<<b);
                                S2|=(1<<b);
                                S3|=(1<<b);
                                cnt++;
                                if(b>0)S2|=(1<<b-1);
                                if(b<m-3)S2|=(1<<b+1);
                            }
                        }
                        if(S1!=val[i-1])continue;
                        if(isSon(val[i],S2)&&isSon(val[i+1],S3)){
                            if(dp[i][S2][S3]==-1){
                                dp[i][S2][S3]=dp[i-1][s1][s2]+cnt;
                            }
                            else{
                                dp[i][S2][S3]=min(dp[i][S2][S3],dp[i-1][s1][s2]+cnt);
                            }
                        }
                    }
                }
            }
        }
        if(dp[n-1][val[n-1]][val[n]]==-1)
            printf("Image #%d: impossible\n\n",cas);
        else
            printf("Image #%d: %d\n\n",cas,dp[n-1][val[n-1]][val[n]]);
    }
    return 0;
}
发布了773 篇原创文章 · 获赞 345 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/104530315
今日推荐