我想这一题大家应该不会想看英文的题目吧
楼主就不让你们头疼了,附上翻译
洪水!
题目描述
Flood是Google+平台上一款引人入胜的益智游戏。游戏界面如下:
在游戏开始时,系统将随机生成一个N×N的正方形棋盘,棋盘的每个网格都由六种颜色之一绘制。
玩家从左上角开始。在每一步中,他/她选择一种颜色,并将与左上角连接的所有网格更改为该特定颜色。
“两个网格连接”的说法意味着,在这条路径上的每对相邻网格颜色相同且共享一条边的情况下,这两个网格之间存在一条路径。
通过这种方式,玩家可以从起始网格(左上角)淹没棋盘的区域,直到所有网格的颜色都相同。下图显示了4×4游戏的最早步骤(颜色标记为0到5):
在开始时给定一个彩色棋盘,请找到赢得游戏的最小步数(将所有网格更改为相同的颜色)。
输入格式
输入包含的测试用例不超过20个。对于每个测试用例,第一行包含一个整数N(2<=N<=8),表示游戏板的大小。
以下N行显示了代表游戏板的N×N矩阵(ai,j)N×N。ai、j在表示相应网格的颜色的0到5的范围内。
输入以N=0结束。
输出格式
对于每个测试用例,输出一个整数,表示赢得游戏的最小步数。
输入样例1:
2
0 0
0 0
3
0 1 2
1 1 2
2 2 1
0
输出样例1:
0
3
裸的IDA*(具体内容详见IDA*知识点讲解&&[SCOI2005]骑士精神-CSDN博客)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int N=10;
int mx[5]={0,1,0,-1,0},my[5]={0,0,1,0,-1};
int mp[N][N];
int vis[N][N];
int n;
bool cvis[6];
int count(){
int res=0;
memset(cvis,0,sizeof cvis);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
if(vis[i][j]!=1 && !cvis[mp[i][j]]){
cvis[mp[i][j]]=1; res++;
}
}
return res;
}
void move(int x,int y,int c){
vis[x][y]=1;
for(int i=1;i<=4;i++){
int nx=x+mx[i],ny=y+my[i];
if(nx<1||nx>n||ny<1||ny>n||vis[nx][ny])continue;
if(mp[nx][ny]==c) move(nx,ny,c);
else vis[nx][ny]=2;
}
return;
}
bool solve(int color){
bool flag=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
if(mp[i][j]==color && vis[i][j]==2 ){
move(i,j,color);
flag=1;
}
}
return flag;
}
int dep;
bool DFS(int now){//我就不叫IDAstar怎么滴,看你怎么滴我
if(now==dep)return count()==0;
if(now+count()>dep)return false;
for(int k=0;k<=5;k++){
int cpy[9][9];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cpy[i][j]=vis[i][j];
if(!solve(k))continue;
if(DFS(now+1))return true;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
vis[i][j]=cpy[i][j];
}
return false;
}
int main(){
int i,j;
while(scanf("%d",&n)&&n){
memset(vis,0,sizeof vis);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&mp[i][j]);
move(1,1,mp[1][1]);
for(dep=0;;dep++){
if(DFS(0))break;
}
printf("%d\n",dep);
}
return 0;
}