zoukankan      html  css  js  c++  java
  • 题解西电OJ (Problem 1006

    题目链接 : http://acm.xidian.edu.cn/land/problem/detail?problem_id=1006

    Description

      wm最近喜欢上一种无聊的转盘解锁游戏,他每天都会为这游戏消磨上三个小时的时间。这游戏由三个正六边形拼成,拼成后一共有13个点,其中有4个黑点和9个白点,如下图。每一步可以顺时针或逆时针转动三个六边形的任意一个60度,转动时六边形的顶点也会相应转动,而这游戏的目的是把四个黑点都转到中间(图中最后一个状态)。这是一个很简单的游戏,想达到游戏目的并不难,但wm觉得这样没挑战性,他决定对于任意一个初始状态,用最少的步数去玩这个游戏。

    Input
      输入包含多组数据(500组),EOF结束。
    每组数据都只有一行13个字符的01串,以从上到下,从左到右的点的顺序表示初始状态(这个由三个正六边形拼成图形最上面一排两个点编号为1 2,第二排三个点编号为3 4 5,依此类推,最后一个点编号为13。第一组样例为上图的初始状态),其中1表示黑点0表示白点。
    Output
      每组数据输出一行,解出游戏需要的最小步数。
    Sample Input
    0000000101011
    1011000001000
    Sample Output
    3
    2
     
     
    题解:
    每个六边形,可以朝两个方向旋转,共有3个六边形,共每个状态可以变化到其他六个状态。
    假设初始状态是S,剩下变换后的六个状态分别是S1, S2, S3, S4, S5, S6 。
    一个状态最快旋转得到期望结果的最小次数假定是 Res[S], 那么有以下结论:
    Res[S] = min{Res[S1], Res[S2],Res[S3],Res[S4], Res[S5],Res[S6]}  +  1  ;
    那么这个问题变得简单了,其实就是一个递归可以解决的问题。但是这不是ACM的精神,因为这个方法不是最优的,想想哪里可以优化,
    递归的方法会出现大量的重复计算,因为S状态执行3次S1 和 执行3次S2后会得到相同的状态,为了避免这种重复的计算我们采用动态规划算法。
    初始状态是期望的结果S=0x348 (二进制为  0001101001000),0标示白色,1标示黑色,上图中1序号位置对应的2进制数字的最低位,依次类推。
    初始的Res[0x348] = 0 ;
    初始状态S[0] = 0x348 ;
    然后分别计算,从S[0] 经过1次变换可得到的6种状态,这六种状态的Res为1,然后依次计算, 状态的最大数是0x1E00 (二进制为1111000000000)
     
    附上代码实现:
     1 #include "stdio.h"
     2 
     3 // change status
     4 int turn(int status,int op)
     5 {
     6     static int ops[6][6]={ 
     7         {0, 2, 5, 8, 6, 3}, {0, 3, 6, 8, 5, 2},
     8         {1, 3, 6, 9, 7, 4},    {1, 4, 7, 9, 6, 3},
     9         {6, 8, 10, 12, 11, 9}, {6, 9, 11, 12, 10, 8}};
    10 
    11 
    12     //// trans status to node status
    13     int node[13]={} ;
    14     int tmp , i ;
    15     for(i = 0 ; status ; status>>=1) {
    16         node[i++] = status & 1 ;
    17     }
    18     //// do operation , and get res
    19     
    20     for(tmp = node[ops[op][i=0]]; i < 5 ; i++){
    21         node[ops[op][i]] = node[ops[op][i+1]] ;
    22     }
    23     node[ops[op][5]] = tmp ;
    24     for(i = 0 ; i < 13 ; i++){
    25         status |= node[i]<<i ;
    26     }
    27     return status ;
    28 }
    29 
    30 
    31 
    32 int main()
    33 {
    34     ///// the max number status is 1111000000000 , is 0x1E00
    35     int status[int(0x1E01)] = {} ;
    36     int res[int(0x1E01)] = {} ;
    37     ///// final status is 0001101001000 , is 0x348
    38     res[int(0x348)] = 0 ;
    39     status[0] = 0x348 ;
    40     int s_sum = 1 ;
    41     int i , j ;
    42     char str[13] = {};
    43     ///// Cal the res array
    44     for(i = 0 ; i < s_sum ; i++){
    45         for(j = 0 ; j < 6 ; j++){
    46             int next_s = turn(status[i],j);
    47             if(res[next_s]<=0){
    48                 res[next_s] = res[status[i]] + 1 ;
    49                 status[s_sum++] = next_s ;
    50             }
    51         }
    52     }
    53     ///output answer
    54     for(;scanf("%s",str)!=EOF;printf("%d
    ",res[j])){
    55         for(i = 0 , j = 0 ; i < 13 ; i++){
    56             j |= (str[i]-'0')<<i ;
    57         }
    58     }
    59     return 0;
    60 }

     

  • 相关阅读:
    读书笔记,《我还是喜欢东京——带你感受城市细节》
    学习笔记:Maven的ArcheType的学习笔记
    如何从中企动力(新网)转移域名到阿里云(万网)
    Maven自定义Archetype(zz)
    读书笔记,《Java 8实战》第五章,使用流
    读书笔记,《Java 8实战》,第四章,引入流
    读书笔记,《Java 8实战》,第三章,Lambda表达式
    读书笔记,《Java8实战》第一章,为什么要关心 Java8
    读书笔记,《深入理解java虚拟机》,第三章 垃圾收集器与内存分配策略
    行业知识:关于发电量与碳排放和等效植树的换算关系
  • 原文地址:https://www.cnblogs.com/liucheng/p/3668511.html
Copyright © 2011-2022 走看看