The Clocks

【原题链接】

【题意说明】

一组9面钟的初始时间点数,时间只能为3、6、9、12这四种整点数,再给出9种拨动钟表的方案,每次每面钟最多能顺时针拨动90度,即由3->6,6->9,9->12,12->3。问最少使用几种方案,就可使所有的钟表都拨到12点!若使用拨动方案数相同,则输出字典序最小的方案。

9面钟编号:

A B C
  D E F
  G H I

移动方案:

1  ABDE
  2  ABC
  3  BCEF
  4  ADG
  5  BDEFH
  6  CFI
  7  DEGH
  8  GHI
  9  EFHI

【问题分析】

首先我思考的是搜索,求最优,如何保存状态呢?状态压缩,可以看出:每种方案最多使用0~3次(因为使用4次就相当于没有使用),所以最多的状态为4^9=26144,经过编码,完全可以保存下来,而且搜索的时间复杂度应该不算太高!当然如果使用dfs,完全无视空间的状态存储(基本不会栈溢出了)!只需要考虑一下适当的剪枝,进行优化即可!

这里再来说说非搜索的思路:

(1)所有的钟面只有4种状态(3,6,9,12),对就可转化为(1,2,3,0)

(2)所有的方案只能拨动某些钟面到下一个状态,如方案1可拨动A、B、D、E,其它的不能拨动,我们可以把它扩展记为1 1 0 1 1 0 0 0 0,表示对9面钟的控制状态。这样所有的方案转化为:

1 1 0 1 1 0 0 0 0
  1 1 1 0 0 0 0 0 0
  0 1 1 0 1 1 0 0 0
  1 0 0 1 0 0 1 0 0
  0 1 0 1 1 1 0 1 0
  0 0 1 0 0 1 0 0 1
  0 0 0 1 1 0 1 1 0
  0 0 0 0 0 0 1 1 1
  0 0 0 0 1 1 0 1 1

这样可以看出这个表(记录A[i][j])中的每列都是控制一面钟,若假定每种方案的使用次数为b[i],每面钟的初始状态为c[i],这样就可以计算出每面钟最少需要拨动几次就能达到目标状态,修改c[i]的值为最少拨动的次数。这样我们就可以建立以下的方程:

sum(A[i][j]*b[i])%4=c[j](其中b[i]表示第i种方案使用的次数,且0≤b[i]≤3)

写成一般方程组形式为:Ab=c -->b=A-1c,(其中:A为方程的系数矩阵,A-1为矩阵的逆)

这样我只要求出矩阵A的逆,即可计算出b[i]的值。由数论的知识可知通过初等行变换,可以把A|E-->E|A-1,注意在求逆的过程中,要加遇负转正,且要模4的处理,最终计算得A-1为:

3 3 3 3 3 2 3 2 0
  2 3 2 3 2 3 1 0 1
  3 3 3 2 3 3 0 2 3
  2 3 1 3 2 0 2 3 1
  2 3 2 3 1 3 2 3 2
  1 3 2 0 2 3 1 3 2
  3 2 0 3 3 2 3 3 3
  1 0 1 3 2 3 2 3 2
  0 2 3 2 3 3 3 3 3

至此,我们就可以通过二重循环以求得每个b[i]的值,即:

b[i]=sum(A-1[i][j]*c[j])%4

最后按要求输出这些b[i]的值即可。

原文地址:https://www.cnblogs.com/ahmasoi/p/2762399.html