codevs 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

本题解直接搜索过了

剪枝见注释

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 using namespace std;
  6 struct Node
  7 {
  8     int x,y;
  9 }q[100001];
 10 const int dx[5]={0,1,-1,0,0};
 11 const int dy[5]={0,0,0,1,-1};
 12 int a[11][11],n,color[6],ans=2e9;
 13 bool v[6],vg[11][11];
 14 void find()
 15 {int h,t,i;
 16     memset(v,0,sizeof(v));
 17     memset(vg,0,sizeof(vg));
 18     h=0;t=1;
 19     int c=a[1][1];
 20     q[1]=(Node){1,1};
 21     vg[1][1]=1;
 22     while (h<t)
 23     {
 24         h++;
 25         for (i=1;i<=4;i++)
 26          {
 27             int x=q[h].x+dx[i],y=q[h].y+dy[i];
 28              if (x>=1&&x<=n&&y>=1&&y<=n)
 29              {
 30                 if (!vg[x][y])
 31                 {if (a[x][y]==c)
 32                  {
 33                     t++;
 34                     q[t]=(Node){x,y};
 35                  }
 36                  else if (a[x][y]!=c) v[a[x][y]]=1;
 37                  vg[x][y]=1;
 38                 }
 39              }
 40          }
 41     }
 42 }
 43 int change(int c)
 44 {int h,t,i,cnt;
 45     h=0;t=1;
 46     q[1]=(Node){1,1};
 47     int cc=a[1][1];
 48      a[1][1]=c;
 49       cnt=1;
 50     while (h<t)
 51     {
 52         h++;
 53         for (i=1;i<=4;i++)
 54          {
 55             int x=q[h].x+dx[i],y=q[h].y+dy[i];
 56              if (x>=1&&x<=n&&y>=1&&y<=n&&a[x][y]==cc)
 57              {
 58                 a[x][y]=c;
 59                 t++;
 60                 q[t]=(Node){x,y};
 61                 cnt++;
 62              }
 63          }
 64     }
 65     return cnt;
 66 }
 67 void dfs(int step)
 68 {int i,j,map[11][11];
 69     bool vis[6];
 70     int cnt=0;
 71     for (i=0;i<=5;i++)
 72     if (color[i]) cnt++;
 73     if (cnt==1)
 74     {
 75         ans=min(ans,step);
 76         return;
 77     }
 78     if (cnt+step>ans) return;//最优性剪枝,当剩下种类+当前步数>ans则明显舍去
 79     find();//只变成有在周围存在的颜色
 80     memcpy(map,a,sizeof(map));
 81     memcpy(vis,v,sizeof(vis));//重点,因为深搜会改变v
 82     for (i=0;i<=5;i++)
 83      if (vis[i])
 84      {
 85         int c=a[1][1];
 86         int x=change(i);
 87         color[c]-=x;color[i]+=x;
 88         dfs(step+1);
 89         memcpy(a,map,sizeof(a));
 90         color[c]+=x;color[i]-=x;
 91      }
 92 }
 93 int main()
 94 {int i,j;
 95     while (cin>>n&&n)
 96     {ans=2e9;
 97     memset(color,0,sizeof(color));
 98     for (i=1;i<=n;i++)
 99     for (j=1;j<=n;j++)
100     {
101         scanf("%d",&a[i][j]);
102         color[a[i][j]]++;
103     }
104      dfs(0);
105     cout<<ans<<endl;
106     }
107 }
时间: 2024-10-04 14:13:56

codevs 2495 水叮当的舞步的相关文章

codevs 2495 水叮当的舞步IDA*

/* 比较简单的A* 估价函数很简单就是除了左上角的联通快之外的不同的个数 加上迭代 好像答案最多在16步之内出解 这样裸裸的交上去是50分 在考虑剪枝 每个选颜色的时候一定是选左上角联通快附近的颜色 处理一下只枚举这样的颜色 80 - 90 分了就 下面是代码 */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,ans,g[9][9],a[9][9],t

【wikioi】2495 水叮当的舞步(A*+迭代加深搜索)

这题我还是看题解啊囧.(搜索实在太弱.完全没想到A*,还有看题的时候想错了,.,- -) 好吧,估价还是那么的简单,判断颜色不同的数目即可(左上角的联通块不算在内) 然后A*还是一样的做法. 迭代加深还是一样的味道- 在这里我们用c[i][j]来表示左上角开始的联通块和联通块外面一层(因为要从外面一层拓展颜色),分别记为1和2 那么我们在搜索的时候,染色只要染c[i][j]为2的颜色种类,并且更新联通块(在这里不需要传图,因为一层一层的拓展下去的话,是单调递增的,所以用不到之前的颜色)我们在搜索

bzoj 3041: 水叮当的舞步 迭代加深搜索 &amp;&amp; NOIP RP++

3041: 水叮当的舞步 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 72  Solved: 44[Submit][Status] Description 水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变.为了讨好她的偶像虹猫,水叮当决定在地毯上跳一支轻盈的舞来卖萌~~~地毯上的格子有N行N列,每个格子用一个0~5之间的数字代表它的颜色.水叮当可以随意选择一个0~5之间的颜色,然后轻轻地跳动一步

BZOJ 3041 水叮当的舞步

3041: 水叮当的舞步 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 120  Solved: 67[Submit][Status][Discuss] Description 水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变.为了讨好她的偶像虹猫,水叮当决定在地毯上跳一支轻盈的舞来卖萌~~~地毯上的格子有N行N列,每个格子用一个0~5之间的数字代表它的颜色.水叮当可以随意选择一个0~5之间的颜色

水叮当的舞步 深搜

背景 Background 水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变. 为了讨好她的偶像虹猫,水叮当决定在地毯上跳一支轻盈的舞来卖萌~~~ 描述 Description 地毯上的格子有N行N列,每个格子用一个0~5之间的数字代表它的颜色. 水叮当可以随意选择一个0~5之间的颜色,然后轻轻地跳动一步,左上角的格子所在的联通块里的所有格子就会变成她选择的那种颜色.这里连通定义为:两个格子有公共边,并且颜色相同. 由于水叮当是施展轻功来跳舞的,

【codevs2495】水叮当的舞步

题目描述 Description 水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变.为了讨好她的偶像虹猫,水叮当决定在地毯上跳一支轻盈的舞来卖萌~~~ 地毯上的格子有N行N列,每个格子用一个0~5之间的数字代表它的颜色.水叮当可以随意选择一个0~5之间的颜色,然后轻轻地跳动一步,左上角的格子所在的联通块里的所有格子就会变成她选择的那种颜色.这里连通定义为:两个格子有公共边,并且颜色相同.由于水叮当是施展轻功来跳舞的,为了不消耗过多的真气,她想知道

水叮当的舞步

[题目描述] 地毯上的格子有N行N列,每个格子用一个0~5之间的数字代表它的颜色.水叮当可以随意选择一个0~5之间的颜色,然后轻轻地跳动一步,左上角的格子所在的联通块里的所有格子就会变成她选择的那种颜色.这里连通定义为:两个格子有公共边,并且颜色相同.水叮当想知道最少要多少步才能把所有格子的颜色变成一样的. [输入描述] 每个测试点包含多组数据.每组数据的第一行是一个整数N,表示地摊上的格子有N行N列:接下来一个N*N的矩阵,矩阵中的每个数都在0~5之间,描述了每个格子的颜色:N=0代表输入的结

codevs2495 水叮当的舞步

题目描述 Description 水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变. 为了讨好她的偶像虹猫,水叮当决定在地毯上跳一支轻盈的舞来卖萌~~~ 地毯上的格子有N行N列,每个格子用一个0~5之间的数字代表它的颜色. 水叮当可以随意选择一个0~5之间的颜色,然后轻轻地跳动一步,左上角的格子所在的联通块里的所有格子就会变成她选择的那种颜色.这里连通定义为:两个格子有公共边,并且颜色相同. 由于水叮当是施展轻功来跳舞的,为了不消耗过多的真气,她

「Poetize5」水叮当的舞步

Description 水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变. 为了讨好她的偶像虹猫,水叮当决定在地毯上跳一支轻盈的舞来卖萌~~~ 地毯上的格子有N行N列,每个格子用一个0~5之间的数字代表它的颜色. 水叮当可以随意选择一个0~5之间的颜色,然后轻轻地跳动一步,左上角的格子所在的联通块里的所有格子就会变成她选择的那种颜色.这里连通定义为:两个格子有公共边,并且颜色相同. 由于水叮当是施展轻功来跳舞的,为了不消耗过多的真气,她想知道最少