1. 程式人生 > >codevs 2495 水叮當的舞步

codevs 2495 水叮當的舞步

const 地毯 output 隨著 深搜 cst mes body nbsp

題目描述 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 }

codevs 2495 水叮當的舞步