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 }

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com