拨钟问题

传送门: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  } 

 

posted @ 2019-03-03 12:06  敲代码不BB  阅读(1787)  评论(0编辑  收藏  举报