当前位置: 首页 > news >正文

UVA11212 EditingaBook ( IDA*搜索)

首先说说IDS,就DFS限定一个层数上限maxd,如果在maxd范围内没有找到解,就增加maxd,继续搜索。

当访问到当前结点u时,估计还要搜索h(u)层,如果h(u)+当前层数d>maxd的时候就剪枝,这就是IDA*。

IDA*属于DFS,当状态空间某一层的结点数无穷大时,BFS失效,只能DFS。

相比BFS,它的空间占用少(不需要判重复),时间效率也不低。

注意:A*的关键在于选取估价函数h()。

----------------------------------分割线-------------------------------------------------------------

来说说 UVA11212 EditingaBook

 

缩小搜索空间的策略有

策略1:只剪切连续的数字片段。

策略2:剪切的片段头为a尾为b,要么粘贴到a-1的后面,要么粘贴到b+1前面。

策略3:不要破坏已经连续的片段。

但是策略1和策略2并能保证正解:如5 4 3 2 1 —》 3 2 5 4 1 —》 3 4 1 2 5 -》 1 2 3 4 5。

策略1,2出错主要是因为忽略了后效性,策略3是可以的,把连续的片段看成整体,拆开它一定是比不拆它的步数要少。

下面寻找估价函数

由于每次剪切最多更改3个数字的前继(或后继),所以统计前继不对的数字个数为n个那么只少还要搜n/3层。如果d+n/3>maxd即3*d+n>maxd就剪枝。

还有一个剪枝是:移动片段b1~b2到b2+1~c后面,相当于移动b2+1~c到b1~b2前面,所以只要枚举把片段往后移动就行了。

//Rey
#include<bits/stdc++.h>

const int maxn = 9;

int n,a[maxn];

inline bool End()
{
    for(int i = 1; i < n; i++){
        if(a[i] <= a[i-1]) return false;
    }
    return true;
}

inline int h()
{
    int cnt = 0;
    for(int i = 1; i < n; i++)
        if(a[i] != a[i-1]+1) cnt++;
    return cnt;
}

int maxd;
const int intsz = sizeof(int);
const int asz = sizeof(a);
bool dfs(int d)
{
    if(3*d + h() > 3*maxd) return false;
    if(End()) return true;

    int old[maxn];//保存a
    memcpy(old,a,asz);
    int b[maxn];//剪切板

    for(int i = 0; i < n; i++) if( i == 0 || old[i] != old[i-1] + 1) //策略3 选择尽量长的连续片段 剪切的起点
    for(int j = i; j < n; j++) { //终点 和 策略2不同选取片段可以不连续
        while(j+1 < n && old[j+1] == old[j] + 1)j++;//策略3
        memcpy(b,old+i,intsz*(j-i+1));
        //剪切移动片段
        for(int k = j+1;k < n;k++){//由于对称性,只要往后贴就行了
            while(k+1 < n && old[k+1] == old[k] + 1)k++;//策略3 不破坏
            memcpy(a+i,old+j+1,intsz*(k-j));
            memcpy(a+i+k-j,b,intsz*(j-i+1));
            if(dfs(d+1))return true;
            //恢复
            memcpy(a,old,asz);
        }
    }
    return false;
}

inline int solve()
{
    if(End())return 0;
    for(maxd = 1; maxd < 5 ;maxd++)
        if(dfs(0)) return maxd;
    return 5;
}
int main()
{
    //freopen("in.txt","r",stdin);
    int Cas = 0;
    while(~scanf("%d",&n)&&n) {
        for(int i = 0; i < n; i++)
            scanf("%d",a+i);
        int ans = solve();
        printf("Case %d: %d\n",++Cas,ans);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/jerryRey/p/4629805.html

相关文章:

  • TreeMap的介绍
  • Treemap的应用
  • 《Effective C++》——条款04:确定对象使用前已先被初始化
  • Treemap的使用
  • 数组根据index拆分和查询下标
  • include指令和include动作的区别
  • sql-主键即自增长的设置及语法实现
  • android中的样式主题和国际化
  • sql-go的使用
  • sql 获取新插入的id值的三种方法
  • 关于WCF SessionId的说明
  • idea中的jsp依赖
  • html5页面中拨打电话的方式
  • Cron表达式
  • 参数修饰符ref,out,params的区别
  • SegmentFault for Android 3.0 发布
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • IndexedDB
  • iOS | NSProxy
  • Js基础知识(一) - 变量
  • 分享几个不错的工具
  • 复杂数据处理
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 两列自适应布局方案整理
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 说说动画卡顿的解决方案
  • 一个SAP顾问在美国的这些年
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 栈实现走出迷宫(C++)
  • 说说我为什么看好Spring Cloud Alibaba
  • ​configparser --- 配置文件解析器​
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • ​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (12)Linux 常见的三种进程状态
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (Forward) Music Player: From UI Proposal to Code
  • (差分)胡桃爱原石
  • (二)windows配置JDK环境
  • (附源码)python旅游推荐系统 毕业设计 250623
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (附源码)计算机毕业设计SSM在线影视购票系统
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (推荐)叮当——中文语音对话机器人
  • (转)程序员疫苗:代码注入
  • **python多态
  • .java 9 找不到符号_java找不到符号
  • .mysql secret在哪_MYSQL基本操作(上)
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .net websocket 获取http登录的用户_如何解密浏览器的登录密码?获取浏览器内用户信息?...
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • .net 验证控件和javaScript的冲突问题
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .NET中的Exception处理(C#)