zoukankan      html  css  js  c++  java
  • 拨钟问题

    传送门: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  } 
  • 相关阅读:
    多态
    封装,继承,多态
    基本类型和引用类型的区别
    第七天 面向对象
    什么是Java线程池
    游戏内核架构
    放松
    静不下来心写代码
    速度和正确率
    理顺思路
  • 原文地址:https://www.cnblogs.com/knmxx/p/10464594.html
Copyright © 2011-2022 走看看