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]的值即可。

  • 相关阅读:
    前天去游泳了
    Microsoft今天开了中文的MSDN了,以后查资料有时要快了点吧
    Visual Studio .NET已检测到指定的WEB服务运行的不是ASP.NET 1.1版
    sqlserver 2005 利用游标解决标量值函数主键自增id批量导入数据问题
    nvarchar查询条件中不用加单引号''吗?
    使用标量值函数作为主键自增值的时候,动软代码生成器的插入方法需要去掉主键的参数。
    c#里的'0','1'对应sqlserver2005中的False,True
    三元运算符绑定缩略内容
    循环插入数据存储过程
    01|02|03| ====> (01,02,03)用于in id数组这种查询方式
  • 原文地址:https://www.cnblogs.com/ahmasoi/p/2762399.html
Copyright © 2011-2022 走看看