https://nanti.jisuanke.com/t/43393
题意:
给出的图案,用十字的盖章,最少需要盖几次。盖章必须整个盖到图案上
解析:
对于第i行放置十字的情况,前面的行能影响的区域为红色区域。也就是14个格子。
对于第i行,有7个位置可以填十字。由于左右两个格子是否为空直接影响两边的十字能否填,所以有5个十字。
表示填完第i行,第i行的7个位置的状态为s1,第i+1行的7个位置的状态为s2的最少十字数量。
从上一行转移时,枚举中间的5个十字,i-1行为s1,i行为s2,i+1行为s3。要求s1与地图中的相同。s2,s3可以是地图子集。
而14个格子由于下面行一定比上面行少,所以枚举子集复杂度为 。
最大复杂度为
代码:
/*
* 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;
}