http://acm.hdu.edu.cn/showproblem.php?pid=4127
模拟题
染色时候,选择格数较多的。然后迭代加深搜索,再考虑还剩下多少颜色,就可以减枝减过去了。确实很难的一道搜索。。。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
const int INF = 10000;
using namespace std;
int n;
struct Grid{
char g[8][8];
bool vis[8][8];
int sum[6];
int cur;
vector<int> block[6];
Grid(){
cur=0;
memset(vis,0,sizeof(vis));
}
int check(){
int ans=0;
for(int i=0;i<6;i++)if(sum[i])ans++;
return ans;
}
void paint(int c){
cur=c;
for(int i=0;i<block[cur].size();i++){
flood(block[cur][i]/8,block[cur][i]%8);
}
block[cur].clear();
}
void flood(int x,int y){
if(vis[x][y])return;
if(g[x][y]!=cur){block[g[x][y]].push_back(x*8+y);return;}
sum[cur]--;
vis[x][y]=true;
if(x-1>=0)flood(x-1,y);
if(x+1<n)flood(x+1,y);
if(y-1>=0)flood(x,y-1);
if(y+1<n)flood(x,y+1);
}
vector<int> get_seq(){
vector<int> ans;
bool v[6]={0};
for(int i=0;i<6;i++){
int u=-1;
int m=0;
for(int j=0;j<6;j++){
if(!v[j]&&block[j].size()){
if(block[j].size()>m){
u=j;
m=block[j].size();
}
}
}
if(u==-1)break;
ans.push_back(u);
v[u]=true;
}
return ans;
}
};
int limit;
int d;
int ans;
bool dfs(Grid &a){
if(a.check()==0){
ans=min(d,ans);
return true;
}
if(d+a.check()>=limit)return false;
vector<int> seq=a.get_seq();
for(int i=0;i<seq.size();i++){
Grid b=a;
b.paint(seq[i]);
d++;
if(dfs(b))return true;
d--;
}
}
int main(){
while(~scanf("%d",&n)){
if(n==0)break;
Grid a;
memset(a.vis,0,sizeof(a.vis));
memset(a.sum,0,sizeof(a.sum));
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
scanf("%d",&a.g[i][j]);
a.sum[a.g[i][j]]++;
}
}
a.cur=a.g[0][0];
a.block[a.g[0][0]].push_back(0);
d=-1;
ans=INF;
for(limit=0;limit<1000;limit++){
if(dfs(a))break;
}
printf("%d\n",ans);
}
}