UVA-1343 The Rotation Game (IDA*)

题目大意:数字1,2,3都有八个,求出最少的旋转次数使得图形中间八个数相同。旋转规则:对于每一长行或每一长列,每次旋转就是将数据向头的位置移动一位,头上的数放置到尾部。若次数相同,则找出字典序最小旋转次序。

题目分析:IDA*,若当前在第cur层,中间八个数中1,2,3的个数分别为a,b,c。则d=8-max(a,b,c)便是达到目标还需要的理想次数,若cur+d>maxd,则剪枝。《入门经典》上提供了一种BFS的思路,分别以1,2,3为目标广搜3次,不过自己的码力还是太弱,并没有用那种方法AC。。。!!!

代码如下:

# include<iostream>
# include<cstdio>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std;

int a[24],d[8][7]={
    {0,2,6,11,15,20,22},
    {1,3,8,12,17,21,23},
    {10,9,8,7,6,5,4},
    {19,18,17,16,15,14,13},
    {23,21,17,12,8,3,1},
    {22,20,15,11,6,2,0},
    {13,14,15,16,17,18,19},
    {4,5,6,7,8,9,10},
};
int g[8]={6,7,8,11,12,15,16,17};
int ans;
string ansp;

bool dfs(int cur,int maxd,string path)
{
    if(cur==maxd){
        int ok=1;
        for(int i=1;i<8;++i)
            if(a[g[i]]!=a[g[i-1]]){
                ok=0;
                break;
            }
        if(!ok)
            return false;
        ans=a[g[0]],ansp=path;
        return true;
    }
    int b[3]={0,0,0};
    for(int i=0;i<8;++i)
        ++b[a[g[i]]-1];
    int dd=8-max(max(b[0],b[1]),b[2]);
    if(cur+dd>maxd)
        return false;
    for(int i=0;i<8;++i){
        int v=a[d[i][0]];
        for(int j=0;j<6;++j)
            a[d[i][j]]=a[d[i][j+1]];
        a[d[i][6]]=v;
        if(dfs(cur+1,maxd,path+char(i+‘A‘)))
            return true;
        v=a[d[i][6]];
        for(int j=6;j>0;--j)
            a[d[i][j]]=a[d[i][j-1]];
        a[d[i][0]]=v;
    }
    return false;
}

int main()
{
    while(scanf("%d",&a[0])&&a[0])
    {
        for(int i=1;i<24;++i)
            scanf("%d",a+i);

        ans=-1;
        for(int maxd=0;;++maxd){
            if(dfs(0,maxd,"")){
                if(maxd==0)
                    printf("No moves needed\n");
                else
                    cout<<ansp<<endl;
                printf("%d\n",ans);
                break;
            }
        }
    }
    return 0;
}

  

时间: 2024-09-30 03:31:50

UVA-1343 The Rotation Game (IDA*)的相关文章

1343 - The Rotation Game (IDA*算法)

紫书上给的是状态空间搜索,其实本题也可以用IDA*算法,因为其符合IDA*的特点 : 求最小迭代次数 . 根据旋转的规律,我们可以用几个数组来储存向各个方向旋转时改变哪些量,用来维护旋转这个操作 .另外就是估价函数:当前出现在中间八个格子中次数最多的数字设为t ,那么剩下的迭代次数就是8 - t  , 如果它加上已经迭代的次数d > maxd ,则应当剪枝 . 另外想到了一个估算回溯法的时间复杂度的好办法 : 一般在每一层进入下一层的可能数设为t , 最大迭代次数设为 d  , 那么时间复杂度为

POJ - 2286 - The Rotation Game (IDA*)

IDA*算法,即迭代加深的A*算法,实际上就是迭代加深+DFS+估价函数 题目传送:The Rotation Game AC代码: #include <map> #include <set> #include <list> #include <cmath> #include <deque> #include <queue> #include <stack> #include <bitset> #include

UVA - 1343 The Rotation Game (BFS/IDA*)

题目链接 紫书例题. 首先附上我第一次bfs+剪枝TLE的版本: 1 #include<bits/stdc++.h> 2 3 using namespace std; 4 typedef long long ll; 5 const int N=24+2,inf=0x3f3f3f3f; 6 const int b[][10]= { 7 {0,2,6,11,15,20,22}, 8 {1,3,8,12,17,21,23}, 9 {10,9,8,7,6,5,4}, 10 {19,18,17,16,1

POJ 2286 The Rotation Game(IDA*)

The Rotation Game Time Limit: 15000MS   Memory Limit: 150000K Total Submissions: 6396   Accepted: 2153 Description 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

【UVa】1374 Power Calculus(IDA*)

题目 题目 ? ? 分析 IDA*大法好,抄了lrj代码. ? ? 代码 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxans=14; int n,a[maxans+1]; bool dfs(int d,int maxd) { if(a[d] == n) return true; if(d == maxd) return false;

Uva 10815-Andy&#39;s First Dictionary(串)

Problem B: Andy's First Dictionary Time limit: 3 seconds Andy, 8, has a dream - he wants to produce his very own dictionary. This is not an easy task for him, as the number of words that he knows is, well, not quite enough. Instead of thinking up all

UVA 10791 Minimum Sum LCM (数论)

LCM (Least Common Multiple) of a set of integers is defined as the minimum number, which is a multiple of all integers of that set. It is interesting to note that any positive integer can be expressed as the LCM of a set of positive integers. For exa

UVA 10375 Choose and divide(数论)

The binomial coefficient C(m,n) is defined as m! C(m,n) = -------- n!(m-n)! Given four natural numbers p, q, r, and s, compute the the result of dividing C(p,q) by C(r,s). The Input Input consists of a sequence of lines. Each line contains four non-n

uva:10700 - Camel trading(贪心)

题目:10700 - Camel trading 题目大意:给出一些表达式,表达式由数字和加号乘号组成,数字范围[1,20].这些表达式可能缺少了括号,问这样的表达式加上括号后能得到的最大值和最小值. 解题思路:因为这些数的都是正整数,所以可以用贪心.不然看出最大值就是先做完加法在做乘法,最小值就是先做乘法在做加法.注意这里的数值要用long long 因为比表达式的值可能会超过int. 代码: #include <stdio.h> #include <string.h> cons