题意:通过剪切粘贴操作,将n个自然段组成的文章,排列成1,2,……,n。剪贴板只有一个,问需要完成多少次剪切粘贴操作可以使文章自然段有序排列。

分析:

1、IDA*搜索:maxn是dfs的层数上限,若在maxn范围内未找到解,则++maxn,直到找到解。对于每个当前深度deep,若还需要搜索m层才能找到解,而deep+m>maxn,则剪枝。

2、对于本题,选取估价函数,若当前深度下,后继不正确的数字个数是m,则还需要m/3层才能找到解。即若deep+m/3>maxn则剪枝。

3、不断枚举剪切片段,并将其粘贴到后面。

4、剪切区间是一段一段的连续数字,连续数字的长度可为1。

#pragma comment(linker, "/STACK:102400000, 102400000")
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define Min(a, b) ((a < b) ? a : b)
#define Max(a, b) ((a < b) ? b : a)
typedef long long ll;
typedef unsigned long long llu;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ll LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {, , -, , -, -, , };
const int dc[] = {-, , , , -, , -, };
const int MOD = 1e9 + ;
const double pi = acos(-1.0);
const double eps = 1e-;
const int MAXN = 1e5 + ;
const int MAXT = + ;
using namespace std;
int a[];
int maxn;
int n;
bool judge(){//自然段是否有序排列
for(int i = ; i < n; ++i){
if(a[i - ] > a[i]) return false;
}
return true;
}
int getCount(){//后继不正确的数字个数
int cnt = ;
for(int i = ; i < n; ++i){
if(a[i - ] + != a[i]) ++cnt;
}
return cnt;
}
bool dfs(int deep){//当前深度
if( * deep + getCount() > * maxn) return false;//剪枝
if(judge()) return true;
int save[];//暂存a数组,便于恢复数组a
int cut[];
memcpy(save, a, sizeof(a));//save暂存a
for(int i = ; i < n; ++i){//枚举剪切起点
if(!i || a[i - ] + != a[i]){//剪切起点
for(int j = i; j < n; ++j){//枚举剪切终点
while(j + < n && a[j] + == a[j + ]) ++j;//当前的j为剪切区间的终点,剪切保证永远不要“破坏”一个已经连续排列的数字片段
memcpy(cut, save + i, sizeof (int) * (j - i + ));//剪切区间放在cut里
for(int k = j + ; k < n; ++k){//枚举粘贴起点
while(k + < n && a[k] + == a[k + ]) ++k;//粘贴起点保证不破坏连续排列的数字片段,k为最后确定的粘贴起点
memcpy(a + i, save + j + , sizeof(int) * (k - j));
memcpy(a + i + k - j, cut, sizeof(int) * (j - i + ));//这两步完成了将剪切片段粘贴到下标k后面
if(dfs(deep + )) return true;
memcpy(a, save, sizeof(a));//sizeof(a)是数组a所占内存的长度,该修改不成立,恢复数组a
}
}//剪切区间是一段一段的连续数字,连续数字的长度可为1
}
}
return false;//所有剪切粘贴情况都不成立
}
int solve(){
if(judge()) return ;//不需要剪切粘贴
for(maxn = ; ; ++maxn){//枚举深度
if(dfs()) return maxn;
}
}
int main(){
int kase = ;
while(scanf("%d", &n) == ){
if(!n) return ;
for(int i = ; i < n; ++i){
scanf("%d", a + i);
}
int ans = solve();
printf("Case %d: %d\n", ++kase, ans);
}
return ;
}

UVA - 11212 Editing a Book(IDA*算法+状态空间搜索)的更多相关文章

  1. UVa 11212 Editing a Book (IDA* && 状态空间搜索)

    题意:你有一篇n(2≤n≤9)个自然段组成的文章,希望将它们排列成1,2,…,n.可以用Ctrl+X(剪切)和Ctrl+V(粘贴)快捷键来完成任务.每次可以剪切一段连续的自然段,粘贴时按照顺序粘贴.注 ...

  2. UVA - 11212 Editing a Book (IDA*)

    给你一个长度为n(n<=9)的序列,每次可以将一段连续的子序列剪切到其他地方,问最少多少次操作能将序列变成升序. 本题最大的坑点在于让人很容易想到许多感觉挺正确但实际却不正确的策略来避开一些看似 ...

  3. UVA 11212 Editing a Book [迭代加深搜索IDA*]

    11212 Editing a Book You have n equal-length paragraphs numbered 1 to n. Now you want to arrange the ...

  4. UVA 11212 Editing a Book

    题意: 有一篇由n个自然段组成的文章.希望将他们排成递增序列.只能剪贴和粘贴交替进行,剪贴时可以剪贴一段连续的自然段. 分析: 用IDA*算法求解.当3*d+h>maxd时剪枝. 代码: #in ...

  5. UVA - 11212 Editing a Book (IDA*搜索)

    题目: 给出n(1<n<10)个数字组成的序列,每次操作可以选取一段连续的区间将这个区间之中的数字放到其他任意位置.问最少经过多少次操作可将序列变为1,2,3……n. 思路: 利用IDA* ...

  6. uva 11212 - Editing a Book(迭代加深搜索 IDA*) 迭代加深搜索

    迭代加深搜索 自己看的时候第一遍更本就看不懂..是非常水,但智商捉急也是没有办法的事情. 好在有几个同学已经是做过了这道题而且对迭代加深搜索的思路有了一定的了解,所以在某些不理解的地方询问了一下他们的 ...

  7. Editing a Book UVA - 11212 IDA*

    You have n equal-length paragraphs numbered 1 to n . Now you want to arrange them in the order of 1 ...

  8. UVa 1343 The Rotation Game (状态空间搜索 && IDA*)

    题意:有个#字型的棋盘,2行2列,一共24个格. 如图:每个格子是1或2或3,一共8个1,8个2,8个3. 有A~H一共8种合法操作,比如A代表把A这一列向上移动一个,最上面的格会补到最下面. 求:使 ...

  9. UVa 1374 Power Calculus (IDA*或都打表)

    题意:给定一个数n,让你求从1至少要做多少次乘除才可以从 x 得到 xn. 析:首先这个是幂级的,次数不会很多,所以可以考虑IDA*算法,这个算法并不难,难在找乐观函数h(x), 这个题乐观函数可以是 ...

随机推荐

  1. sentinel控制台

    下载sentinel源码包:https://github.com/alibaba/Sentinel/tree/master,根据自己需要下载不同版本的分支,博主下载得是1.6 下载后解压,然后进入se ...

  2. 一套完整的javascript面试题(转)

    一.单选题1.以下哪条语句会产生运行错误:(a)A.var obj = ();//语法错误B.var obj = [];//创建数组C.var obj = {};//创建对象D.var obj = / ...

  3. Linux CentOS7 VMware 安装软件包的三种方法、rpm包介绍、rpm工具用法、yum工具用法、yum搭建本地仓库

    一.安装软件包的三种方法 Linux下游三种安装方法,rpm工具.yum工具.源码包.rpm按装一个程序包时,有可能因为该程序包依赖另一个程序包而无法安装:yum工具,可以连同依赖的程序包一起安装. ...

  4. JDBC--Statement使用

    1.通过Statement实现类执行更新操作(INSERT.UPDATE .DELETE): --1)获取数据库连接Connection的对象: --2)通过Connection类的createSta ...

  5. Kotlin 学习 (一)

    开始学习kotlin mark入门资料一篇: Kotlin入门第一课:从对比Java开始 未完待续...

  6. ffmpeg 学习:000-概述和库的组成

    背景 ffmpeg bin工具 可能无法满足产品的使用,于是需要通过传参调用ffmpeg库,即在通过更底层的方式使用它. FFmpeg 介绍 FFmpeg是领先的多媒体框架,能够解码,编码,转码,复用 ...

  7. 新闻网大数据实时分析可视化系统项目——17、Spark2.X分布式弹性数据集

    1.三大弹性数据集介绍 1)概念 2)优缺点对比 2.Spark RDD概述与创建方式 1)概述 在集群背后,有一个非常重要的分布式数据架构,即弹性分布式数据集(resilientdistribute ...

  8. Python Sphinx使用踩坑记录

    描述 使用 pip 安装sphinx后,按照教程建立了一个新的py文件,如下 # run.py def run(name): """ this is how we run ...

  9. Linux每日练习-awk命令之内部自定义函数 20200224

  10. python --- 日志模块 logging

    1.日志的使用 import logging class CommonLog(object): def _common_log(self,level,message): # 设定收集器,再设定收集的级 ...