zoukankan      html  css  js  c++  java
  • 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]的值即可。

  • 相关阅读:
    Pycharm 调试system-config-users
    只写了两行代码,为什么要花两天时间?
    为开源做贡献的6个技巧
    2020年10月编程语言排行榜
    全球最厉害的 14 位程序员
    6_38_二叉树的后序遍历非递归算法(和先序有些许不一样)
    6_37_二叉树的先序遍历非递归算法
    6_36_相似二叉树
    6_33_两个一维数组判断u是否为v的子孙
    6_34_扩展判断u是否为v的子孙
  • 原文地址:https://www.cnblogs.com/ahmasoi/p/2762399.html
Copyright © 2011-2022 走看看