Flood-it!

我想这一题大家应该不会想看英文的题目吧

楼主就不让你们头疼了,附上翻译

洪水!
题目描述
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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值