HDU-1667

首先放上我的思路:似乎有点找到IDA*的感觉了

#include <bits/stdc++.h>
using namespace std;
/*
这道题似乎用IDA*和BFS都可以 
但为了保险起见还是使用IDA*避免内存过大
注意要移动距离最短的
*/
int result;//最后相同数字
int board[8][8];//储存当前棋局的状态
string move;//储存移动方式
//判断当前棋盘状态是否符合中间八个一样的
bool checked() {

}
//八种移动方法
//按照字母顺序移动 使得满足字典序最小(题目要求)
void dir(int i) {

}
void ida(int now,int dep) {
    //checked 设置flag为true return 设置result
    //剪枝 :如果8-当前中间最多的元素的个数比当前dep-now还要大 
    //说明不可能到达 return;
    //开始dfs 八种可能
    //最后回溯

}
int main() {
    //读取到board数组中 当读取0 退出;
    //从深度1 开始迭代加深搜索 设置flag 当flag=1时候break;
    return 0;
}

下面是大神的写法 似乎跟我的思路差不多 并且如果是互逆操作剪枝 这个是没有想到的 

转载自:hdu1667-IDA*-迭代加深搜索 A*算法_a*算法的改进迭代加深a*搜索-CSDN博客

#include <bits/stdc++.h>
using namespace std;

const int center[] = {6,7,8,11,12,15,16,17};  //中心8个点坐标
const int reverseop[] = {5,4,7,6,1,0,3,2,-1};  //每种操作的逆操作
const int index[8][7] = {  //从A-H操作变动的下标
    { 0,2,6,11,15,20,22 },    //A
    { 1,3,8,12,17,21,23 },    //B
    { 10,9,8,7,6,5,4 },       //C
    { 19,18,17,16,15,14,13 }, //D
    { 23,21,17,12,8,3,1 },    //E
    { 22,20,15,11,6,2,0 },    //F 
    { 13,14,15,16,17,18,19 }, //G
    { 4,5,6,7,8,9,10 },       //H
};
int mp[24];
char finop[105];  //搜到目标的操作序列
bool flag;  //是否搜到目标

int get_h()
{
    int cnt[3]={0};
    int num=-1;
    for(int i=0;i<8;i++)
    {
        cnt[mp[center[i]]-1]++;
        num = max(num,cnt[mp[center[i]]-1]);
    }
    return 8-num;
}

void option(int op)
{
    int tmp=mp[index[op][0]];
    for(int i=0;i<6;i++)
    {
        mp[index[op][i]] = mp[index[op][i+1]];
    }
    mp[index[op][6]]=tmp;
}

void dfs(int depth,int lastop,int maxdepth)  //depth当前深度 lastop上一次的操作 maxdepth每次迭代加深搜索的最大深度
{
    if(flag) return;
    if(depth>maxdepth || depth+get_h()>maxdepth) return;  //可行性剪枝
    if(get_h()==0)  //中心相同了
    {
        flag=true;
        finop[depth]='\0';
        printf("%s\n%d\n",finop,mp[center[0]]);
        return;
    }
    for(int nextop=0;nextop<8;nextop++)  //从A开始搜索
    {
        if(nextop!=reverseop[lastop])  //与上一次操作不互逆
        {
            option(nextop);
            finop[depth]=nextop+'A';
            dfs(depth+1,nextop,maxdepth);
            option(reverseop[nextop]);  //回溯还原
        }
    }
}

int main()
{
    while(1)
    {
        for(int i=0;i<24;i++)
        {
            scanf("%d",&mp[i]);
            if(mp[i]==0) return 0;
        }
        if(get_h()==0)
        {
            printf("No moves needed\n%d\n", mp[center[0]]);
            continue;
        }
        flag=false;
        for(int depth=1;!flag;depth++) //迭代加深
        {
            dfs(0,8,depth);
        }
    }
    return 0;
}

几个重要的点:

1.剪枝

2.互逆跳过

3.不规则结构的存储和移动

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值