铁盘整理c++代码

本文介绍了如何解决一个关于调整铁盘中整数顺序的问题,通过深度优先搜索(DFS)、广度优先搜索(BFS)和IDA*算法,优化搜索策略,预估步数以减少操作次数并实现剪枝,最终找到最小操作次数。
摘要由CSDN通过智能技术生成

对于一个小于16的n,我们首先肯定能够想到搜索,关键是搜什么,怎么搜,用什么方法搜?
我们首先面临的问题是铁盘大小,对于这个问题直接离散化,使铁盘成为一个1~n的全排列
第二个问题,直接dfs会活生生的爆掉,bfs会让你处于MLE无法自拔,我们于是用我们的优化技巧迭代加深。确定一个搜索深度,用\Theta(1)Θ(1)空间复杂度去求得答案
然后就会T爆
考虑剪枝。我们通读题面,发现我们一次操作翻转了1~x的铁盘,我们发现,啊,我们最多改变两个铁盘之差,按我们的最优方法,如果现在还有y个相邻铁盘差值不为1,我们至少执行y次操作
但是注意,我们翻转1~n也相当于改变了差值,所以说我们需要将moved_{n+1}moved
n+1
设成n+1n+1
所以说我们在一开始的时候预估步数,然后搜索就完了
其实这就是IDA*IDA∗,预估步数就是预估函数,在这里能起到剪枝的作用

#include<cstdio>
#include<algorithm>
#include<queue>
#include<bitset>
using namespace std;
int n,iron[55],moved[55],depth=0;
int Abs(int x){return x<0?-x:x;}
void init(){for(int i=1;i<=n;++i)    moved[i]=iron[i];}
bool iddfs(int now)
{
    int error=0;
    for(int i=1;i<=n;++i)    if(Abs(moved[i]-moved[i+1])>1)    ++error;
    if(now+error>depth)    return false;//预估步数,加上已有步数进行计算
    if(now==depth)
    {
        for(int i=1;i<=n;++i)    if(moved[i]!=i)    return false;
        return true;
    }//判断是否合法
    bool flag=false;
    for(int i=2;i<=n;++i)
    {
        for(int j=1;j<=(i>>1);++j)    swap(moved[i-j+1],moved[j]);
        flag|=iddfs(now+1);
        for(int j=1;j<=(i>>1);++j)    swap(moved[i-j+1],moved[j]);//进行搜索
        if(flag)    return true;
    }
    return false;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i)    scanf("%d",&iron[i]),moved[i]=iron[i];
    sort(moved+1,moved+1+n);
    for(int i=1;i<=n;++i)    for(int j=1;j<=n;++j)    if(iron[i]==moved[j])
    {
        iron[i]=j;
        break;
    }//离散化
    moved[n+1]=n+1;
    do    init(),++depth;    while(!iddfs(0));//id
    printf("%d",depth);
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值