【IDA*】codevs 2495:水叮当的舞步

2495 水叮当的舞步

  

题目描述 Description

  水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变。
  为了讨好她的偶像虹猫,水叮当决定在地毯上跳一支轻盈的舞来卖萌~~~

  地毯上的格子有N行N列,每个格子用一个0~5之间的数字代表它的颜色。
  水叮当可以随意选择一个0~5之间的颜色,然后轻轻地跳动一步,左上角的格子所在的联通块里的所有格子就会变成她选择的那种颜色。这里连通定义为:两个格子有公共边,并且颜色相同。
  由于水叮当是施展轻功来跳舞的,为了不消耗过多的真气,她想知道最少要多少步才能把所有格子的颜色变成一样的。

输入描述 Input Description

  每个测试点包含多组数据。
  每组数据的第一行是一个整数N,表示地摊上的格子有N行N列。
  接下来一个N*N的矩阵,矩阵中的每个数都在0~5之间,描述了每个格子的颜色。
  N=0代表输入的结束。

输出描述 Output Description

  对于每组数据,输出一个整数,表示最少步数。

样例输入 Sample Input

  2
  0 0 
  0 0
  3 
  0 1 2 
  1 1 2
  2 2 1
  0

样例输出 Sample Output

  0
  3

数据范围及提示 Data Size & Hint

  对于30%的数据,N<=5
  对于50%的数据,N<=6
  对于70%的数据,N<=7
  对于100%的数据,N<=8,每个测试点不多于20组数据。

第二组样例解释:
  0 1 2       1 1 2       2 2 2      1 1 1
  1 1 2 --> 1 1 2 --> 2 2 2 --> 1 1 1
  2 2 1       2 2 1       2 2 1      1 1 1


 

   一开始打了一个四不像的搜索。。只有30..

  后来瞄了一眼题解。。

  发现解题思路还是很神的

  估价函数比较裸:当前剩余颜色数目

  剩下就是怎么搜索了

  把图分为3种颜色

  与(1,1)在一个同色联通块里为1 

  在联通块边界但是不与联通块同色为2

  剩下为0

  每次变颜色搜遍整个图然后把与要变颜色相同的且颜色为2的格子拓展一下

  最后都是1的时候退出

  IDA*

  

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<algorithm>
  5 
  6 using namespace std;
  7 
  8 int n=99,map[11][11],X[4]={0,0,1,-1},Y[4]={1,-1,0,0},MAP[11][11];
  9 
 10 bool g[11][11];
 11 
 12 void pre(int x,int y,int col)
 13 {
 14     MAP[x][y]=1;
 15     if(x==1&&y==1)col=map[1][1];
 16     for(int i=0;i<4;i++)
 17     {
 18     int xx=x+X[i],yy=y+Y[i];
 19     if(xx<=n&&yy<=n&&xx>=1&&yy>=1&&MAP[xx][yy]!=1)
 20     {
 21         if(map[xx][yy]==col)pre(xx,yy,col);
 22         else MAP[xx][yy]=2;
 23     }
 24     }
 25 }
 26 
 27 /*void ran(int x,int y,int col)
 28 {
 29     for(int i=0;i<4;i++)
 30     {
 31     int xx=x+X[i],yy=y+Y[i];
 32     if(xx<=n&&yy<=n&&xx>=1&&yy>=1&&map[xx][yy]==map[1][1]&&(!(xx+yy==2&&xx==1)))
 33         map[xx][yy]=col,ran(xx,yy,col);
 34     }
 35     }*/
 36 
 37 int get()
 38 {
 39     int res[6]={0},nu=1;
 40     for(int i=1;i<=n;i++)
 41     for(int j=1;j<=n;j++)
 42         if(!res[map[i][j]] && MAP[i][j]!=1)
 43         {
 44         res[map[i][j]]=1;
 45         nu++;
 46         }
 47     return nu;
 48 }
 49 
 50 void dfs(int x,int y,int col)
 51 {
 52     MAP[x][y]=1;
 53     for(int i=0;i<4;i++)
 54     {
 55     int xx=X[i]+x,yy=y+Y[i];
 56     if(xx<=n&&yy<=n&&xx>=1&&yy>=1&&MAP[xx][yy]!=1)
 57     {
 58         if(map[xx][yy]==col)dfs(xx,yy,col);
 59         else MAP[xx][yy]=2;
 60     }
 61     }
 62 }
 63 
 64 bool fill(int col)
 65 {
 66     int ret=0;
 67     for(int i=1;i<=n;i++)
 68     for(int j=1;j<=n;j++)
 69         if(MAP[i][j]==2&&map[i][j]==col)
 70         {
 71         ret++;
 72         dfs(i,j,col);
 73         }
 74     return ret;
 75 }
 76 
 77 bool IDA(int k)
 78 {
 79     /*memset(g,0,sizeof(g));
 80     int stop=find(1,1,0),ctrl=0,temp[11][11];
 81     if(!stop)return 1;
 82     else if(!k)return 0;
 83     for(int i=0;i<=5;i++)
 84     if(i!=map[1][1]&&(stop&(1<<i))!=0)
 85     {
 86         memcpy(temp,map,sizeof(map));
 87         ran(1,1,i);
 88         map[1][1]=i;
 89         ctrl=IDA(k-1);
 90         if(!ctrl)memcpy(map,temp,sizeof(temp));
 91         else return 1;
 92        }
 93     return 0;*/
 94     int nu=get();
 95     if(nu==1)return 1;
 96     else if(k+1<nu)return 0;
 97     int temp[11][11]={0};
 98     for(int i=0;i<=5;i++)
 99     {
100     memcpy(temp,MAP,sizeof(MAP));
101     if(fill(i) && IDA(k-1))return 1;
102     memcpy(MAP,temp,sizeof(temp));
103     }
104     return 0;
105 }
106 
107 int main()
108 {
109     while(1)
110     {
111     scanf("%d",&n);
112     if(!n)break;
113     for(int i=1;i<=n;i++)
114         for(int j=1;j<=n;j++)
115         scanf("%d",&map[i][j]);
116     memset(MAP,0,sizeof(MAP));
117     pre(1,1,map[1][1]);
118     for(int i=0;i<=n*n;i++)
119         if(IDA(i)){printf("%d\n",i);break;}
120     }
121     return 0;
122 }
View Code

  

 

 

posted @ 2015-12-16 20:55  puck_just_me  阅读(...)  评论(... 编辑 收藏