UVA_Rotation Game<旋转游戏> UVA 1343

The rotation game uses a # shaped board, which can hold 24 pieces of square blocks (see Fig.1). The blocks
are marked with symbols 1, 2 and 3, with exactly 8 pieces of each kind.
Initially, the blocks are placed on the board randomly. Your task is to move the blocks so that the eight blocks
placed in the center square have the same symbol marked. There is only one type of valid move, which is to
rotate one of the four lines, each consisting of seven blocks. That is, six blocks in the line are moved towards
the head by one block and the head block is moved to the end of the line. The eight possible moves are
marked with capital letters A to H. Figure 1 illustrates two consecutive moves, move A and move C from
some initial configuration.
Input
The input consists of no more than 30 test cases. Each test case has only one line that contains 24 numbers,
which are the symbols of the blocks in the initial configuration. The rows of blocks are listed from top to
bottom. For each row the blocks are listed from left to right. The numbers are separated by spaces. For
example, the first test case in the sample input corresponds to the initial configuration in Fig.1. There are no
blank lines between cases. There is a line containing a single `0‘ after the last test case that ends the input.
Output
For each test case, you must output two lines. The first line contains all the moves needed to reach the final
configuration. Each move is a letter, ranging from `A‘ to `H‘, and there should not be any spaces between the
letters in the line. If no moves are needed, output `No moves needed‘ instead. In the second line, you must
output the symbol of the blocks in the center square after these moves. If there are several possible solutions,
you must output the one that uses the least number of moves. If there is still more than one possible solution,
you must output the solution that is smallest in dictionary order for the letters of the moves. There is no need
to output blank lines between cases.
Sample Input
1 1 1 1 3 2 3 2 3 1 3 2 2 3 1 2 2 2 3 1 2 1 3 3
1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3
0

Sample Output
AC
2
DDHH
2

解题报告

比较基础的IDA*,启发函数就是每次最多只能恢复一个...

代码比较挫(旋转那完全是人工。。。)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int s[24];
int maxd;
char ans[150];

bool input(){
scanf("%d",&s[0]);
if(s[0] == 0) return false;
for(int i = 1;i<=23;++i)
 scanf("%d",&s[i]);
return true;
}

void ope(int i,int * d){
int ch;
if (i == 0)
 {
  ch = d[0];
  d[0] = d[2];
  d[2] = d[6];
  d[6] = d[11];
  d[11] = d[15];
  d[15] = d[20];
  d[20] = d[22];
  d[22] = ch;
 }
else if(i == 1)
 {
   ch = d[1];
   d[1] = d[3];
   d[3] = d[8];
   d[8] = d[12];
   d[12] = d[17];
   d[17] = d[21];
   d[21] = d[23];
   d[23] = ch;
 }
else if(i == 2)
 {
   ch = d[10];
   for(int i = 10;i>=5;--i)
    d[i] = d[i-1];
    d[4] = ch;
 }
else if(i == 3)
 {
   ch = d[19];
   for(int i = 19;i>=14;--i)
    d[i] = d[i-1];
    d[13] = ch;
 }
else if(i == 4)
 {
   ch = d[23];
   d[23] = d[21];
   d[21] = d[17];
   d[17] = d[12];
   d[12] = d[8];
   d[8] = d[3];
   d[3] = d[1];
   d[1] = ch;
 }
else if(i == 5)
 {
     ch = d[22];
     d[22] = d[20];
     d[20] = d[15];
     d[15] = d[11];
     d[11] = d[6];
     d[6]= d[2];
     d[2] = d[0];
     d[0] = ch;
 }
else if(i == 6)
 {
   ch = d[13];
   for(int i = 13;i<=18;++i)
    d[i] = d[i+1];
   d[19] = ch;
 }
else if(i == 7)
 {
   ch = d[4];
   for(int i = 4;i<=9;++i)
    d[i] = d[i+1];
   d[10] = ch;
 }

}

bool dfs(int d,int *t,int tid){
if (d == maxd)
{
  if (t[11] != tid || t[12] != tid) return false;
  for(int i = 6;i<=8;++i)
   if(t[i] != tid)
    return false;
  for(int i = 15;i<=17;++i)
   if(t[i] != tid)
    return false;
  return true;
}
int co = 0;
if (t[11] != tid ) co ++;
if (t[12] != tid) co ++;
for(int i = 6;i<=8;++i)
 if(t[i] != tid)
   co ++;
for(int i = 15;i<=17;++i)
 if(t[i] != tid)
  co ++;
if (co + d > maxd) return false;
for(int i = 0;i<8;++i)
 {
     int nt[24];
     memcpy(nt,t,sizeof(nt));
     ope(i,nt);
     ans[d] = i + ‘A‘;
     if (dfs(d+1,nt,tid)) return true;
 }

return false;
}

int main(int argc,char * argv[]){
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
int targetid,outid;
char outans[150];
while(input())
{
  for(int i = 0;;++i)
   {
       int ok = 0;
       maxd = i ;
       for(int j = 1;j<=3;++j)
            if (dfs(0,s,j))
             {
                 ok++;
                 if (ok == 1)
                 {
                     outid = j;
                 memcpy(outans,ans,sizeof(outans));
                 }

                 if (ok >= 2)
                  {
                      int check = 0;
                      for(int i = 0;i<maxd;++i)
                       if(outans[i] > ans[i])
                        {
                            check = 1;
                           break;
                        }
                        else if(outans[i] < ans[i])
                         break;
                     if(check)
                      {
                          memcpy(outans,ans,sizeof(outans));

                          outid = j;
                      }

                  }
             }
    if(ok)
     break;

   }
  if (maxd == 0)
   cout << "No moves needed" << endl << outid << endl;
  else
   {
       outans[maxd] = ‘\0‘;
       cout << outans << endl << outid << endl;
   }
}

return 0;
}
时间: 2024-08-06 20:07:35

UVA_Rotation Game<旋转游戏> UVA 1343的相关文章

poj 3752 字母旋转游戏

字母旋转游戏 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7890   Accepted: 2983 Description 给定两个整数M,N,生成一个M*N的矩阵,矩阵中元素取值为A至Z的26个字母中的一个,A在左上角,其余各数按顺时针方向旋转前进,依次递增放置,当超过26时又从A开始填充.例如,当M=5,N=8时,矩阵中的内容如下: A B C D E F G H V W X Y Z A B I U J K L

UVa 1343 旋转游戏(dfs+IDA*)

https://vjudge.net/problem/UVA-1343 题意:如图所示,一共有8个1,8个2和8个3,如何以最少的移动来使得中间8个格子都为同一个数. 思路:状态空间搜索问题. 用IDA*算法的话会比较快,而且代码比较简洁. IDA*的关键就是要寻找一个估价函数h(),在这道题目中,每次移动最多只会使一个格子的数字正确,所以当maxd-d<h()时便可以剪枝. 1 #include<iostream> 2 #include<string> 3 #include

09_Sum游戏(UVa 10891 Game of Sum)

问题来源:刘汝佳<算法竞赛入门经典--训练指南> P67 例题28: 问题描述:有一个长度为n的整数序列,两个游戏者A和B轮流取数,A先取,每次可以从左端或者右端取一个或多个数,但不能两端都取,所有数都被取完时游戏结束,然后统计每个人取走的所有数字之和作为得分,两人的策略都是使自己的得分尽可能高,并且都足够聪明,求A的得分减去B的得分的结果. 问题分析:1.设dp[i][j]表示从第i到第j的数的序列中,双方都采取最优策略的前提下,先手得分的最大值 2.若求dp[i][j],我们可以枚举从左边

UVA 1343 The Rotation Game

题意: 给出图,往A-H方向旋转,使中间8个格子数字相同.要求旋转次数最少,操作序列字典序尽量小. 分析: 用一维数组存24个方格.二维数组代表每个方向对应的7个方格.IDA*剪枝是当8-8个方格中重复字母最多的那个字母数量>maxd. 代码: #include <iostream>#include <cstring>#include <algorithm>#include <cstdio>using namespace std;int a[24];i

UVa 1343 The Rotation Game(IDA*)

主要是设计乐观估计函数来减枝 假设中心区域有6个2,2个3,那肯定是消掉3最好,毕竟就两个. 那么理想情况下,旋转一次就能把一个3变成2,那么最少操作2次. 我们用h()来计算最少还要操作几次,其原理是假设中心区域都放1或2或3,返回至少操作的次数中最小的数 maxd是假设最多能操作的数; d是已经操作的数; 那么就可以得出乐观估计函数   h()+d>maxd 其含义为 : 若  至少还要操作次数  加上  已经操作的次数  大于  最多总共操作的次数就退出 . 其次就是节点的处理了,编个号数

UVA 1343 - The Rotation Game-[IDA*迭代加深搜索]

解题思路: 这是紫书上的一道题,一开始笔者按照书上的思路采用状态空间搜索,想了很多办法优化可是仍然超时,时间消耗大的原因是主要是: 1)状态转移代价很大,一次需要向八个方向寻找: 2)哈希表更新频繁: 3)采用广度优先搜索结点数越来越多,耗时过大: 经过简单计算,最长大概10次左右的变换就能出解,于是笔者就尝试采用IDA*,迭代加深搜索的好处是: 1)无需存储状态,节约时间和空间: 2)深度优先搜索查找的结点数少: 3)递归方便剪枝: 代码如下: 1 #include <iostream> 2

uva 1343 非原创

uva1343 原作者 题目题意是:给你的棋盘,在A-H方向上可以拨动,问你最少拨动几次可以是中心图案的数字一致 解题思路:回溯法,剪枝 其中要把每次拨动的字母所代表的位置提前用数组表示: 然后在如果step+h()>maxd表示剪枝. 总之,用数组那里表示真的好棒, 自己太残了……!!! #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include

旋转游戏-题解

总时间限制: 15000ms  内存限制: 150000kB 描述 The rotation game uses a # shaped board, which can hold 24 pieces of square blocks (see Fig.1). The blocks are marked with symbols 1, 2 and 3, with exactly 8 pieces of each kind. Initially, the blocks are placed on t

例题7-12 旋转游戏 UVa1343

1.题目描述:点击打开链接 2.解题思路:本题利用迭代加深搜索解决.好久没做这个专题了,感觉这种方法有点力不从心,不会寻找估价函数是硬伤...只好学一学别人的代码. 本题要求棋盘中间的8个方格都要是相同的数字.紫书上说是利用状态空间搜索解决,大致模板还是八数码问题的模板.但是写了半天最后WA了,感觉这道题用那个模板写出来会很复杂.最后看别人的代码,才发现大多都是利用迭代加深搜索解决的,代码量也不是很大.因此学习这种方法了. 本题的移动比较复杂,因此应当事先保存A,B,C,D四个方向的位置,后四个