UVA1505 Flood-it! 题解
题目链接
此题算法 IDA*
IDA* 是指带有预估函数的迭代加深算法,相比 A-Star 算法,其优势在于节省了优先队列的
IDA* 算法要点:
1 . 控制迭代加深深度。若题目说在
2 . 设计合理的预估函数。预估函数越大,优化越多。但预估函数不可以大于未来实际代价,这是设计预估函数的基本原则。特别的,当预估函数为 0 时,搜索就是爆搜。
分析
首先,由于 N 很小,所以自然想到搜索或者状态压缩。此题选择搜索 (IDA*)。
既然是 IDA* , 那我们先来求预估函数。显然,本题的预估函数
另外,该题不同于 IDA* 模板题的地方就是要扩展一下颜色,代码中详见。代码中的
另外,还有
最后,就是套路的迭代加深了。
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
int n,map[10][10];
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int vis[10][10];
int f(){ //预估函数
int cnt=0;
int t[10]={false}; //桶
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(!t[map[i][j]]&&vis[i][j]!=1){ //在还没有走到的点中求颜色有多少种
cnt++;
t[map[i][j]]=true;
}
return cnt;
}
bool valid(int x,int y){
return x>=1&&x<=n&&y>=1&&y<=n&&vis[x][y]!=1;
}
void expand(int x,int y,int cor){
vis[x][y]=1; //已访问
for(int i=0;i<4;i++){
int xx=x+dx[i];
int yy=y+dy[i];
if(!valid(xx,yy)) continue;
vis[xx][yy]=2; //在访问的边缘
if(map[xx][yy]==cor) expand(xx,yy,cor); //若颜色相同,就还可以扩展
}
}
int change(int cor){
int res=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(vis[i][j]==2&&map[i][j]==cor){ //在扩展边缘上并且颜色与新选的一致
expand(i,j,cor); res++;
}
return res;
}
bool dfs(int dep,int maxdep){
if(dep+f()>maxdep) return false;
if(!f()) return true;
int t[10][10]; //小数组可以开到局部
for(int i=0;i<=5;i++){
memcpy(t,vis,sizeof vis);
if(change(i)&&dfs(dep+1,maxdep)) return true; //change(i)==true 表示此次颜色扩展有效(也就是有新的格子换了颜色)
memcpy(vis,t,sizeof vis); //还原现场
}
return false;
}
int main(){
while(scanf("%d",&n)&&n){
memset(vis,0,sizeof vis); //清空不要忘了
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&map[i][j]);
int maxdep=0;
expand(1,1,map[1][1]); //首先处理处左上角同样颜色的点集
while(!dfs(0,maxdep)) maxdep++; //迭代加深
printf("%d\n",maxdep);
}
return 0;
}