HDU

来源:互联网 发布:淘宝拆分订单付款 编辑:程序博客网 时间:2024/05/17 06:59

Flood-it!

Problem Description
Flood-it is a fascinating puzzle game on Google+ platform. The game interface is like follows:

At the beginning of the game, system will randomly generate an N×N square board and each grid of the board is painted by one of the six colors. The player starts from the top left corner. At each step, he/she selects a color and changes all the grids connected with the top left corner to that specific color. The statement “two grids are connected” means that there is a path between the certain two grids under condition that each pair of adjacent grids on this path is in the same color and shares an edge. In this way the player can flood areas of the board from the starting grid (top left corner) until all of the grids are in same color. The following figure shows the earliest steps of a 4×4 game (colors are labeled in 0 to 5):

Given a colored board at very beginning, please find the minimal number of steps to win the game (to change all the grids into a same color). 

 

Input
The input contains no more than 20 test cases. For each test case, the first line contains a single integer N (2<=N<=8) indicating the size of game board.

The following N lines show an N×N matrix (ai,j)n×n representing the game board. ai,j is in the range of 0 to 5 representing the color of the corresponding grid. 
The input ends with N = 0.
 

Output
For each test case, output a single integer representing the minimal number of steps to win the game.
 

Sample Input
20 0 0 030 1 21 1 22 2 10
 

Sample Output
03
 



解题思路:经典的IDA*搜索题,可用于入门IDA*算法。用dfs不断地加深搜索深度,在当前深度下如果搜到答案,那么就是最少步数。我们注意到,每次上色,可以看看与当前颜色相邻的颜色有多少种,假设有4种如图

0 0 1

0 0 4

2 3 0

那么至少还要填4次色,也就是往下搜索多4层。所以这个可以作为估值函数。详见代码注释。



#include <iostream>#include <stdio.h>#include <stdlib.h>#include <vector>#include <map>#include <string.h>#include <algorithm>#include <queue>using namespace std;int N,MAXD;//MAXD用于IDA*算法的不断加深搜索深度int a[15][15];//原图int vis[15][15];//访问数组,0为没访问过,1为已经上色为相同的颜色,2为1的相邻位置,准备上色。int dx[4]={0,1,0,-1};int dy[4]={1,0,-1,0};//将相同颜色的全部上色void dfsxl(int x,int y,int color){    vis[x][y]=1;//上色    for(int i=0;i<4;i++){        int tx=x+dx[i];        int ty=y+dy[i];        if(tx<0||tx>=N||ty<0||ty>=N)//越界            continue;        if(vis[tx][ty]==1)//已经上色的不用管            continue;        vis[tx][ty]=2;//暂时标记为相邻        if(a[tx][ty]==color)//如果相同颜色,递归上色,如果不是相同颜色,则vis为2            dfsxl(tx,ty,color);    }}//估值函数,这里是看相邻的还有多少种颜色,假设有4种,那么至少还要加深搜索4次。int H(){    int m[8];//标记    int count=0;    memset(m,0,sizeof(m));    for(int i=0;i<N;i++){        for(int j=0;j<N;j++){            if(vis[i][j]==1)                continue;                        if(!m[a[i][j]]){                m[a[i][j]]=1;                count++;            }        }    }    return count;}//将相邻的相同颜色上色,并返回上了多少次int filled(int color){    int count=0;    for(int i=0;i<N;i++)        for(int j=0;j<N;j++){            if(a[i][j] != color)                continue;            //还要是已经搜索过的            if(vis[i][j] == 2){                count++;                dfsxl(i,j,color);            }        }    return count;//返回染色的个数}bool dfs(int d){    //如果是当前最大深度,则判断是否还有需要上色的,没有的话就代表全部已经是同样颜色。    if(d==MAXD)        return H()==0;    //如果估计还要搜索的深度加上当前深度>预定最大深度,则返回false    if(H()+d>MAXD)        return false;    //回到搜索前的状态用的数组    int tempvis[15][15];    memcpy(tempvis,vis,sizeof(vis));    //将6种颜色都尝试上色    for(int i=0;i<6;i++){        //如果发现上色后跟没上色没有区别,即没有一个相邻的颜色与该颜色相同,则不用继续搜了        if(filled(i)==0)            continue;        //往下一层搜        if(dfs(d+1))            return true;        //回到之前状态        memcpy(vis,tempvis,sizeof(vis));    }    return false;}int main(){    while(~scanf("%d",&N)&&N){        for(int i=0;i<N;i++)            for(int j=0;j<N;j++)                scanf("%d",&a[i][j]);        memset(vis,0,sizeof(vis));        //先找出左上角的颜色块        dfsxl(0,0,a[0][0]);                MAXD=0;        do{            if(dfs(0))                break;        }while(++MAXD);//不断加深        printf("%d\n",MAXD);    }    return 0;}




原创粉丝点击