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 }

 

转载于:https://www.cnblogs.com/Y-E-T-I/p/7367875.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值