poj2286The Rotation Game题解(IDA*)

h函数用的是8-中间8个位置出现最多的数的个数
刚开始没注意到字典序wa了一发

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <stack>
#include <vector>
#include <string.h>
#include <queue>
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;
int c1[7]={0,2,6,11,15,20,22},
    c2[7]={1,3,8,12,17,21,23},
    r1[7]={4,5,6,7,8,9,10},
    r2[7]={13,14,15,16,17,18,19},
    mid[8]={6,7,8,11,12,15,16,17};
char indexs[9]="ABCDGHEF";
int sp[8]={0,1,2,3,6,7,4,5};
int arr[24];
int h(int s[])
{
    int res=0;
    for(int k=1;k<4;k++)
    {
        int tmp=0;
        for(int i=0;i<8;i++)
            if(s[mid[i]]==k) tmp++;
        res=max(tmp,res);
    }
    return 8-res;
}
int pathLt;
char path[4313240];
bool IDA(int cur[],int len,int pre)
{
    if(len>=pathLt){
        if(h(cur)) return false;
        else {
            path[len]='\0';
            puts(path);
            printf("%d\n",cur[mid[0]] );
            return true;
        }
    }
    int next[24];
    for(int k=0;k<8;k++)
    {
        int i=sp[k];//将ABCDEFGH转化为ABCDGHEF对应的坐标
        if(i+pre==7) continue;//与上一次移动方向相反
        for(int j=0;j<24;j++) next[j]=cur[j];
        int tmp;
        switch(i)
        {
            case 0: tmp=next[c1[0]];//A
                for(int j=0;j<6;j++)
                    next[c1[j]]=next[c1[j+1]];
                    next[c1[6]]=tmp;
                break;
            case 1: tmp=next[c2[0]];//B
                for(int j=0;j<6;j++)
                    next[c2[j]]=next[c2[j+1]];
                    next[c2[6]]=tmp;
                break;
            case 2: tmp=next[r1[6]];//C
                for(int j=6;j>0;j--)
                    next[r1[j]]=next[r1[j-1]];
                    next[r1[0]]=tmp;
                break;
            case 3: tmp=next[r2[6]];//D
                for(int j=6;j>0;j--)
                    next[r2[j]]=next[r2[j-1]];
                    next[r2[0]]=tmp;
                break;
            case 4: tmp=next[r2[0]];//G
                for(int j=0;j<6;j++)
                    next[r2[j]]=next[r2[j+1]];
                    next[r2[6]]=tmp;
                break;
            case 5: tmp=next[r1[0]];//H
                for(int j=0;j<6;j++)
                    next[r1[j]]=next[r1[j+1]];
                    next[r1[6]]=tmp;
                break;
            case 6: tmp=next[c2[6]];//E
                for(int j=6;j>0;j--)
                    next[c2[j]]=next[c2[j-1]];
                    next[c2[0]]=tmp;
                break;
            case 7: tmp=next[c1[6]];//F
                for(int j=6;j>0;j--)
                    next[c1[j]]=next[c1[j-1]];
                    next[c1[0]]=tmp;
                break;
        }
        path[len]=indexs[i];
        if(len+h(next)<pathLt&&IDA(next,len+1,i))
            return true;
    }
    return false;
}
int main(int argc, char const *argv[])
{
    while(scanf("%d",arr)!=EOF&&arr[0])
    {
        for(int i=1;i<24;i++)
            scanf("%d",arr+i);
        pathLt=h(arr);
        if(!pathLt) {
            puts("No moves needed");
            printf("%d\n",arr[mid[0]]);
            continue;
        }
        while(!IDA(arr,0,-1)) pathLt++;
    }
    return 0;
}
/*
1 1 1 1 3 2 2 2 2 1 3 2 2 3 1 2 2 2 3 1 2 1 3 3
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
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值