IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> IDA*算法 -> 正文阅读

[数据结构与算法]IDA*算法

IDA*算法是迭代加深的A*算法,同时运用了迭代加深全局性最优剪枝,与A*算法比起来,具有以下优点:
(1).不需要判重,不需要排序
(2).空间需求减少
基本思路:
首先将初始状态结点的H值设为阈值maxH,然后进行深度优先搜索,搜索过程中忽略所有H值大于maxH的结点;如果没有找到解,则加大阈值maxH,再重复上述搜索,直到找到一个解。在保证H值的计算满足A*算法的要求下,可以证明找到的这个解一定是最优解。而这里在IDA*算法中也使用合适的估价函数,来评估与目标状态的距离。
在一般的问题中是这样使用IDA*算法的,当前局面的估价函数值+当前的搜索深度 > 预定义的最大搜索深度时,就进行剪枝。
IDA*算法基本框架:

bool dfs(int depth,int max_depth){
    if(depth+f()>max_depth) return false;
    if(check()) return true;
    /*搜索每个分支
   		......
    */
    return false;
}
int main()
{
 
     int depth=0;
     while(!dfs(0,depth)) depth++;//逐步增加搜索的最大层数上限
        
    return 0;
}

例题

acwing180.排书
题意:
给定 n 本书,编号为 1~n。在初始状态下,书是任意排列的。在每一次操作中,可以抽取其中连续的一段,再把这段插入到其他某个位置,我们的目标状态是把书按照1~n 的顺序依次排列,求最少需要多少次操作。
思路:
运用IDA*算法,因为每进行一次操作,最多可以使3个无序连接点排序,当序列有序时应满足q[i]==q[i+1]-1,因此可以设tot为当前书的编号序列中q[i]!=q[i+1]-1的连接点,估价函数设为 f ( s ) = ? t o t / 3 ? f(s)=\left \lceil tot/3 \right \rceil f(s)=?tot/3?
如果当前层数加 f ( s ) f(s) f(s)大于预定义的层数上限,则直接从当前分支回溯

#include<iostream>
#include<algorithm>
#include<queue>
#include<set>
#include<stdlib.h>
#include<time.h>
#include<unordered_map>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<string>
#include<map>
#include<cmath>
#include<bitset>
#define ll long long
#define inf 0x3f3f3f3f
#define bug(a) cout<<"* "<<a<<endl;
#define bugg(a,b) cout<<"* "<<a<<" "<<b<<endl;
#define buggg(a,b,c) cout<<"* "<<a<<" "<<b<<" "<<c<<endl;
using namespace std;
typedef pair<int,int> P;
const int N=15;
const ll mod=1e9+7;

int n;
int q[N];
int w[5][N];
int f(){
    int tot=0;
    for(int i=0;i<n-1;i++){
        if(q[i+1]!=q[i]+1)
            tot++;
    }
    return (tot+2)/3;
}
bool check(){
    for(int i=0;i<n;i++){
        if(q[i]!=i+1)
            return false;
    }
    return true;
}
bool dfs(int depth,int max_depth){
    if(depth+f()>max_depth) return false;//当前状态已操作次数加预估还需操作的次数大于规定的最大的操作次数
    if(check()) return true;
    //搜索每个分支
    for(int len=1;len<=n;len++){
        for(int l=0;l+len-1<n;l++){
            int r=l+len-1;
            for(int k=r+1;k<n;k++){
                memcpy(w[depth],q,sizeof(q));
                int x,y;
                //如果往前移动会有重复操作,所以只进行往后移动即可
                for(x=r+1,y=l;x<=k;x++,y++)
                    q[y]=w[depth][x];
                for(x=l;x<=r;x++,y++)
                    q[y]=w[depth][x];
                if(dfs(depth+1,max_depth)) return true;
                memcpy(q,w[depth],sizeof(q));
            }
        }
    }
    return false;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%d",&q[i]);
        int depth=0;
        while(depth<5&&!dfs(0,depth)) depth++;
        if(depth>=5)
            puts("5 or more");
        else
            printf("%d\n",depth);
    }
    return 0;
}

acwing181.回转游戏

#include<iostream>
#include<algorithm>
#include<queue>
#include<set>
#include<stdlib.h>
#include<time.h>
#include<unordered_map>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<string>
#include<map>
#include<cmath>
#include<bitset>
#define ll long long
#define inf 0x3f3f3f3f
#define bug(a) cout<<"* "<<a<<endl;
#define bugg(a,b) cout<<"* "<<a<<" "<<b<<endl;
#define buggg(a,b,c) cout<<"* "<<a<<" "<<b<<" "<<c<<endl;
using namespace std;
typedef pair<int,int> P;
const int N=24;
const ll mod=1e9+7;

int op[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
};
int q[N];
int center[8]={6,7,8,11,12,15,16,17};
int opsite[8]={5,4,7,6,1,0,3,2};
int path[100];
void operate(int x){
    int tmp=q[op[x][0]];
    for(int i=0;i<6;i++)
        q[op[x][i]]=q[op[x][i+1]];
    q[op[x][6]]=tmp;
}

int f(){//估价函数:f(s)=8-出现次数最多的数字出现的次数
    int sum[4]={0},res=0;
    for(int i=0;i<8;i++)
        sum[q[center[i]]]++;
    for(int i=1;i<=3;i++)
        res=max(sum[i],res);
    return 8-res;
}
bool check(){
    for(int i=0;i<8;i++)
        if(q[center[i]]!=q[6])
            return false;
    return true;
}

bool dfs(int depth,int max_depth,int last){
    if(depth+f()>max_depth) return false;
    if(check()) return true;

    for(int i=0;i<8;i++){
        if(last==opsite[i]) continue;
        operate(i);
        path[depth]=i;
        if(dfs(depth+1,max_depth,i)) return true;
        operate(opsite[i]);
    }
    return false;
}

int main()
{
    while(~scanf("%d",&q[0]),q[0]){
        for(int i=1;i<N;i++)
            scanf("%d",&q[i]);
        int depth=0;
        while(!dfs(0,depth,-1)) depth++;
        if(!depth)
            printf("No moves needed");
        else
            for(int i=0;i<depth;i++)
                printf("%c",path[i]+'A');
        cout<<endl;
        printf("%d\n",q[6]);

    }
    return 0;
}

/*
      0     1
      2     3
4  5  6  7  8   9 10
      11    12
13 14 15 16 17 18 19
      20    21
      22    23
*/



  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-19 01:25:35  更:2022-02-19 01:26:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 15:50:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码