题意:通过剪切粘贴操作,将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. 分页插件 layui.laypage 的用法

    参考 layui.laypage 官方文档 https://www.layui.com/demo/laypage.html 第一步下载插件 (注意不能只引入引入 layui.css和layui.js ...

  2. Maven项目-控制台乱码

    乱码显示: 解决方法:

  3. redis配置文件中常用配置详解

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/suprezheng/article/de ...

  4. Linux关于文件处理命令

    一.登陆用户和机器名称 示例:[root@hadoop01 ~]# root:表示用户名 @hadoop01表示机器名称 ~表示当前文件目录是家目录 #表示输入命令提示符,用户可以在其后输入命令:非r ...

  5. SciPy 线性代数

    章节 SciPy 介绍 SciPy 安装 SciPy 基础功能 SciPy 特殊函数 SciPy k均值聚类 SciPy 常量 SciPy fftpack(傅里叶变换) SciPy 积分 SciPy ...

  6. Ubuntu 19.10将使用GCC 9作为默认编译器

    作为我们这一周期一直期待的变化,Ubuntu 19.10升级到GCC 9作为GCC 8的默认系统编译器. Ubuntu 19.10(和Ubuntu 20.04 LTS)将使用GCC 9 stable作 ...

  7. 51nod 1009:数字1的数量

    1009 数字1的数量 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题  收藏  关注 给定一个十进制正整数N,写下从1开始,到N的所有正数,计算出其中出现所有1的个 ...

  8. redis cluster 添加/删除节点操作

    RedisCluster 添加/删除节点 添加节点新配置两个测试节点8008和9009 [root@--- ~]# /usr/local/redis-/bin/redis-server /u02/re ...

  9. R 读取回归模型的信息

    参考博客: http://blog.sina.com.cn/s/blog_8f5b2a2e0101fmiq.html https://blog.csdn.net/huangyouyu523/artic ...

  10. 二进制中1的个数(n=(n&n-1))

    题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 解题:利用Java系统提供的函数Integer.toBinaryString(n),将整数转化为二进制,之后再将二进制的0用 ...