bzoj1327: The Rotation Game

bzoj1327: The Rotation Game
bz的这个题面啊。……是不是全世界只有没看原题面的我不知道要输出No moves needed……


题解

传说中名为IDA*的剪枝暴搜。
判断一下中间八个格子里最多数字的数量,如果8-这个数要大于深度限制,说明理想情况下这一次也不会出解,于是可以剪掉了。


代码

代码非常丑。
非常丑。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int now[24],loc,ed[]={6,7,8,11,12,15,16,17},tp[4],tot,sol[2017];
int mov[4][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},sad[]={0,0,0,0,1,0,3,2};
bool f;
void read(int &x)
{
    char c=getchar();
    while(c<'0'||c>'9')
    c=getchar();
    x=c-'0';
}
void dfs(int dep)
{
    if(dep<0)return;
    for(int i=1;i<4;i++)
    tp[i]=0;
    for(int i=0;i<8;i++)
    tp[now[ed[i]]]++;
    loc=1;
    for(int i=2;i<4;i++)
    if(tp[loc]<tp[i])
    loc=i;
    if(tp[loc]==8)
    {
        for(int i=0;i<tot;i++)
        putchar(sol[i]+'A');
        printf("\n%d\n",loc);
        f=1;return;
    }
    if(8-tp[loc]>dep)return;
    for(int i=0;i<8&&(!f);i++)
    {
        sol[tot++]=i;
        if(i<4)
        {
            for(int j=6;j;j--)
            swap(now[mov[i][0]],now[mov[i][j]]);
            dfs(dep-1);
            for(int j=0;j<6;j++)
            swap(now[mov[i][6]],now[mov[i][j]]);
        }
        else
        {
            for(int j=0;j<6;j++)
            swap(now[mov[sad[i]][6]],now[mov[sad[i]][j]]);
            dfs(dep-1);
            for(int j=6;j;j--)
            swap(now[mov[sad[i]][0]],now[mov[sad[i]][j]]);
        }
        tot--;
    }
}
int main()
{
    read(now[0]);
    while(now[0])
    {
        for(int i=1;i<24;i++)
        read(now[i]);
        tot=f=0;
        for(int i=1;i<4;i++)
        tp[i]=0;
        for(int i=0;i<8;i++)
        tp[now[ed[i]]]++;
        loc=1;
        for(int i=2;i<4;i++)
        if(tp[loc]<tp[i])
        loc=i;
        if(tp[loc]==8)
        {
            printf("No moves needed\n%d\n",loc);
            f=1;
        }
        for(int i=1;i<2017&&(!f);i++)
        dfs(i);
        read(now[0]);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值