首页 > 技术文章 > [CODEVS 2495]水叮当的舞步

NaVi-Awson 2017-08-14 21:27 原文

Description

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

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

Input

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

Output

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

Sample Input

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

Sample Output

0
3

题解

纯的迭代只有$20$分...

加个$A*$...

我们可以发现,每次寻找左上角的格子所在的联通块耗费的时间常数巨大。因此我们在这里寻求突破。

我们引入一个$N*N$的$v$数组。左上角的格子所在的联通块里的格子标记为$1$。左上角联通块周围一圈格子标记为$2$,其它格子标记为$0$。如果某次选择了颜色$c$,我们只需要找出标记为$2$并且颜色为$c$的格子,向四周扩展,并相应地修改$v$标记,就可以不断扩大标记为$1$的区域,最终如果所有格子标记都是$1$,那么显然找到了答案。

 1 #include<set>
 2 #include<cmath>
 3 #include<ctime>
 4 #include<queue>
 5 #include<stack>
 6 #include<vector>
 7 #include<string>
 8 #include<cstdio>
 9 #include<cstdlib>
10 #include<cstring>
11 #include<iostream>
12 #include<algorithm>
13 #define LL long long
14 #define RE register
15 #define IL inline
16 using namespace std;
17 const int w1[4]={0,0,1,-1};
18 const int w2[4]={1,-1,0,0};
19 
20 int n,lim;
21 int map[10][10];
22 int mark[10][10];
23 
24 int get()
25 {
26     bool vis[6]={0};
27     int t=0;
28     for (RE int i=1;i<=n;i++) for (RE int j=1;j<=n;j++) if (!vis[map[i][j]]&&mark[i][j]!=1)
29     {
30         vis[map[i][j]]=1;
31         t++;
32     }
33     return t;
34 }
35 void Dfs(int a,int b,int x)
36 {
37     mark[a][b]=1;
38     for (int i=0;i<4;i++) if (a+w1[i]>=1&&a+w1[i]<=n&&b+w2[i]>=1&&b+w2[i]<=n&&mark[a+w1[i]][b+w2[i]]!=1)
39     {
40         mark[a+w1[i]][b+w2[i]]=2;
41         if (map[a+w1[i]][b+w2[i]]==x) Dfs(a+w1[i],b+w2[i],x);
42     }
43 }
44 bool fill(int x)
45 {
46     int t = 0;
47     for (RE int i=1;i<=n;i++) for (RE int j=1;j<=n;j++) if (mark[i][j]==2&&map[i][j]==x)
48     {
49         t++;
50         Dfs(i,j,x);
51     }
52     return t;
53 }
54 bool search(int cen)
55 {
56     int v=get();
57     if (!v) return true;
58     if (cen+v>lim) return false;
59     int tmp[10][10];
60     for (int i=0;i<=5;i++)
61     {
62         memcpy(tmp,mark,sizeof(tmp));
63         if (fill(i)) if (search(cen+1)) return true;
64         memcpy(mark,tmp,sizeof(mark));
65     }
66     return false;
67 }
68 
69 int main()
70 {
71     while ((~scanf("%d",&n))&&n)
72     {
73         memset(mark,0,sizeof(mark));
74         for (RE int i=1;i<=n;i++) for (RE int j=1;j<=n;j++) scanf("%d",&map[i][j]);
75         Dfs(1,1,map[1][1]);
76         for (lim=0;;lim++) if (search(0))
77         {
78             printf("%d\n",lim);
79             break;
80         }
81     }
82     return 0;
83 }

 

推荐阅读