撥鍾問題


傳送門: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  } 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM