UVa 1343:The Rotation Game(IDA*)

10 篇文章 0 订阅
9 篇文章 0 订阅

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=841&page=show_problem&problem=4089

题意:如图所示形状的棋盘上分别有8个1,2,3,要往A~H方向旋转棋盘,使中间8个方格数字相同。如图所示。要求旋转次数最少。如果有多解,操作序列的字典序应尽量小。(本段摘自《算法竞赛入门经典(第2版)》)

分析:
可以使用IDA*来求解。由于每次旋转最多使得一个位置从不正确变为正确,则估价函数为 deep+h()<maxd ,deep为当前深度,maxd为最大限制深度, h() 为最小的不正确格子数。

代码:

#include <iostream>
#include <algorithm>
#include <fstream>
#include <cstring>

using namespace std;

const int maxn = 25 + 5;

const int line[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}};
const int rev[8] = {5, 4, 7, 6, 1, 0, 3, 2};
const int center[8] = {6, 7, 8, 11, 12, 15, 16, 17};

int a[maxn];
char init[] = {"No moves needed"};
char ans[1005];

bool judge()
{
    for (int i = 0; i < 8; ++i)
        if (a[center[i]] != a[center[0]])
            return false;
    return true;
}

int h()
{
    int x = 0, y = 0, z = 0;
    for (int i = 0; i < 8; ++i)
    {
        if (a[center[i]] != 1)
            ++x;
        if (a[center[i]] != 2)
            ++y;
        if (a[center[i]] != 3)
            ++z;
    }
    return min(min(x, y), z);
}

void move(int x)
{
    int tmp = a[line[x][0]];
    for (int i = 0; i < 6; ++i)
        a[line[x][i]] = a[line[x][i + 1]];
    a[line[x][6]] = tmp;
}

bool DFS(int deep, int maxd)
{
    if (judge())
    {
        if (deep)
            ans[deep] = '\0';
        return true;
    }
    if (deep + h() > maxd)
        return false;
    for (int i = 0; i < 8; ++i)
    {
        ans[deep] = 'A' + i;
        move(i);
        if (DFS(deep + 1, maxd))
            return true;
        move(rev[i]);
    }
    return false;
}

int main()
{
    while (~scanf("%d", &a[0]), a[0])
    {
        memcpy(&ans, &init, sizeof(init));
        for (int i = 1; i < 24; ++i)
            scanf("%d", &a[i]);
        for (int maxd = 0; ; ++maxd)
            if (DFS(0, maxd))
            {
                printf("%s\n%d\n", ans, a[center[0]]);
                break;
            }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值