傳送門:http://bailian.openjudge.cn/practice/2814?lang=en_US
撥鍾問題,畫家問題,熄燈問題,這三個題有共同的特點:
1.每個開關或者移動的步數是有次數限制的。撥鍾問題移動次數最多為4,因為移動4次跟不移m動一樣,畫家問題和熄燈問題次數為2,因為開關按兩次跟沒按一樣。
2.移動順序或者按開關的順序不重要。都是為了達到目標狀態,先按哪個開關和后按哪個開關不影響最終結果。
3.每次按開關或者移動或影響周圍環境。
下面談談撥鍾問題:
一共有9種移動,每種移動會影響多個鍾,最后要求所有鍾撥到12點的位置。
每個鍾有一個開始狀態0到3,其中,0=12點、1=3點、2=6點、3=9點。最后要求到達12點的位置也就是目標狀態是每個鍾=0。
研究一下9種移動:
移動 影響的時鍾
1 ABDE
2 ABC
3 BCEF
4 ADG
5 BDEFH
6 CFI
7 DEGH
8 GHI
9 EFHI
這樣看可能看不出來啥,把它轉換一下:
時鍾 會被哪些移動影響
A 124
B 1235
C 236
D 1457
E 13579
F 3569
G 478
H 5789
I 689
這樣就很清楚了,用int a[10]記錄每個時鍾的初始狀態,int move[10]記錄9種移動的次數,可以枚舉9種移動的次數(最多為4),
目標是每個鍾經過一系列移動后達到12點,即(a[i]+move[1~9])%4==0,一定要余4,因為表針經過移動后可能會超過一圈。
要使移動序列最短,也就是要使移動次數總和最小,需要設置一個全局變量和全局數組記錄最小次數和相應的移動序列。
1 #include<iostream> 2 #include<string.h> 3 using namespace std; 4 int main() 5 { 6 int a[11]; 7 int change[11]; 8 int best[11]; 9 int minCount = 999999; 10 for(int i = 1;i<=9;++i) 11 { 12 cin >>a[i]; 13 } 14 memset(change,0,sizeof(change));//把change數組里的元素全部初始化為0 15 int sum = 0; 16 //每種移動最多就能進行4次 17 18 for(change[1] = 0;change[1]<4;change[1]++) 19 for(change[2] = 0;change[2]<4;change[2]++) 20 for(change[3] = 0;change[3]<4;change[3]++) 21 for(change[4] = 0;change[4]<4;change[4]++) 22 for(change[5] = 0;change[5]<4;change[5]++) 23 for(change[6] = 0;change[6]<4;change[6]++) 24 for(change[7] = 0;change[7]<4;change[7]++) 25 for(change[8] = 0;change[8]<4;change[8]++) 26 for(change[9] = 0;change[9]<4;change[9]++) 27 { 28 sum = 0; 29 sum+= (a[1]+change[1]+change[2]+change[4])%4;//A 30 sum+= (a[2]+change[1]+change[2]+change[3]+change[5])%4;//B 31 sum+= (a[3]+change[2]+change[3]+change[6])%4;//C 32 sum+= (a[4]+change[1]+change[4]+change[5]+change[7])%4;//D 33 sum+= (a[5]+change[1]+change[3]+change[5]+change[7]+change[9])%4;//E 34 sum+= (a[6]+change[3]+change[5]+change[6]+change[9])%4;//F 35 sum+= (a[7]+change[4]+change[7]+change[8])%4;//G 36 sum+= (a[8]+change[5]+change[7]+change[8]+change[9])%4;//H 37 sum+= (a[9]+change[6]+change[8]+change[9])%4;//I 38 if(sum == 0)//要求最短移動序列 39 { 40 int count = 0; 41 for(int j=1;j<=9;j++) 42 { 43 count += change[j]; 44 } 45 if(count < minCount) 46 { 47 minCount = count; 48 memcpy(best,change,sizeof(change)); 49 } 50 for(int j=1;j<=9;j++) 51 { 52 while(best[j]--) 53 { 54 cout << j<<" "; 55 } 56 } 57 } 58 } 59 return 0; 60 }