一看题感觉像炮兵布阵类似的状压
写了半天发现是假的解法:这题有一个更强的限制就是要填满,
所以状压dp的话要用dp[i][s][ss]表示第i行的颜色状态和填色策略,
或者外层用3^n复杂度的枚举子集来做
算了一下这么一来时间复杂度就不对了O(3^n*2^n*n)
其实可以直接用dfs剪枝搜索
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> using namespace std; char Map[10][10]; int T,N,M,Ans,Case=0; void DFS(int i,int j,int Step,int Count){ if(Step>=Ans) return; if(Count==0){Ans=min(Ans,Step);return;} if(i==1 || i>=N || j==1 || j>=M) return; if((Count-1)/5+1+Step>=Ans) return; char temp[5]; int Cnt=0;bool flag=false; temp[0]=Map[i][j]; temp[1]=Map[i-1][j];temp[2]=Map[i+1][j]; temp[3]=Map[i][j-1];temp[4]=Map[i][j+1]; for(register int k=0;k<5;++k){ if(temp[k]=='#') ++Cnt; if(temp[k]=='.'){flag=true;break;} } if(!flag && Cnt){ Map[i][j]=Map[i-1][j]=Map[i+1][j]=Map[i][j-1]=Map[i][j+1]='@'; if(j+1<M) DFS(i,j+1,Step+1,Count-Cnt); else DFS(i+1,2,Step+1,Count-Cnt); Map[i][j]=temp[0]; Map[i-1][j]=temp[1];Map[i+1][j]=temp[2]; Map[i][j-1]=temp[3];Map[i][j+1]=temp[4]; } if(i==2 && Map[1][j]=='#') return; if(j==2 && Map[i][1]=='#') return; if(i==N-1 && Map[N][j]=='#') return; if(j==M-1 && Map[i][M]=='#') return; if(j+1<M) DFS(i,j+1,Step,Count); else DFS(i+1,2,Step,Count); return; } int main(){ ios::sync_with_stdio(false); cin>>T; while(T--){ ++Case; cout<<"Image #"<<Case<<": "; cin>>N>>M; Ans=2147483647; int Count=0; for(register int i=1;i<=N;++i){ for(register int j=1;j<=M;++j){ cin>>Map[i][j]; if(Map[i][j]=='#') ++Count; } } if(Map[1][1]=='#'||Map[1][M]=='#'||Map[N][1]=='#'||Map[N][M]=='#'){ cout<<"impossible"<<endl<<endl; continue; } DFS(2,2,0,Count); if(Ans==2147483647) cout<<"impossible"<<endl; else cout<<Ans<<endl; cout<<endl; } return 0; }