11212 Editing a Book
  You have n equal-length paragraphs numbered 1 to n. Now you want to arrange them in the order of
1, 2, . . . , n. With the help of a clipboard, you can easily do this: Ctrl-X (cut) and Ctrl-V (paste) several
times. You cannot cut twice before pasting, but you can cut several contiguous paragraphs at the same
time - they’ll be pasted in order.
For example, in order to make {2, 4, 1, 5, 3, 6}, you can cut 1 and paste before 2, then cut 3 and
paste before 4. As another example, one copy and paste is enough for {3, 4, 5, 1, 2}. There are two
ways to do so: cut {3, 4, 5} and paste after {1, 2}, or cut {1, 2} and paste before {3, 4, 5}.
Input
  The input consists of at most 20 test cases. Each case begins with a line containing a single integer n
(1 < n < 10), thenumber of paragraphs. The next line contains a permutation of 1, 2, 3, . . . , n. The
last case is followed by a single zero, which should not be processed.
Output
  For each test case, print the case number and the minimal number of cut/paste operations.
Sample Input
6
2 4 1 5 3 6
5
3 4 5 1 2
0
Sample Output

Case 1: 2
Case 2: 1

解题思路:

  1.简单分析我们可以发现,当n=9时,最多只需要剪切八次即可完成排序。并且全排列数量9!=362880不算很大,所以我们可以将当前排列作为状态,转化成十进制数存入set以便判重。然后逐渐增加解答树的深度(搜索最大深度)进行迭代加深搜索。

  2.构造启发函数。本题可以定义一个后继错数:当前状态中,后继元素不正确的元素个数。可以证明,每一次剪切粘贴最多改变3个数的后继数,那么错数最多减少3.比如  1 2 4 3,错数是3,1 2 3 4,错数是0. 假设当前搜索到第d层,最大搜索深度为maxd,那么如果当前状态的错数 h>3*(maxd-d),则说明这个状态无解,剪枝;

  3.状态转移:以长度递增的顺序,依次从每个元素开始剪切相应长度的一段,然后依次插入后继元素之后(用链表存储序列更方便剪切和插入操作)。

代码如下(关键内容有注释):

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>
#include <ctime>
using namespace std; #define print_time_ printf("time : %f\n",double(clock())/CLOCKS_PER_SEC)
const int maxn=;
set<int> v;//存储状态
int next_[maxn+];//用链表存储当前序列
int n;
int maxd; inline int Atoi(int *next){ //将当前序列转换成十进制数
int ans=;
for(int i=next[],j=;j<n;j++,i=next[i])
ans=ans*+i;
return ans;
}
inline bool isvisited(int *A){//判重
return v.count(Atoi(A));
}
inline void push_v(int *A){
v.insert(Atoi(A));
}
int h(int *next){//获得当前状态下的错数
int h=;
for(int i=next[],j=;j<=n;j++,i=next[i]){
if(j<n){
if(i==n||(i!=n&&next[i]!=i+))
h++;
}
else if(i!=n)
h++;
}
return h;
}
int get_r(int& l,int& len){ //获得被剪切段的最右端
int r=l;
for(int i=;i<len-;i++)
r=next_[r];
return r;
}
bool IDA(int d){
if(d==maxd){
if(h(next_)==)
return true;
else return false;
}
int h_=h(next_);
if(h_>*(maxd-d))
return false;
for(int len=;len<n;len++){
for(int last=,l=next_[],j=;j+len-<=n;j++,last=l,l=next_[l]){ int r=get_r(l, len); for(int ptr=next_[r],i=j+len;i<=n;i++,ptr=next_[ptr]){ next_[last]=next_[r];
next_[r]=next_[ptr];
next_[ptr]=l; if(!isvisited(next_)){ push_v(next_);//被访问
if(IDA(d+))
return true;
v.erase(Atoi(next_));//不要漏掉这一句!!
}
next_[ptr]=next_[r];
next_[r]=next_[last];
next_[last]=l; }
}
}
return false;
}
void init(){
memset(next_, , sizeof next_);
v.clear();
}
int main() {
int T=;
while(scanf("%d",&n)&&n){
T++;
init();
for(int i=,j=;j<n;i=next_[i],j++){
scanf("%d",&next_[i]);
} for(maxd=;;maxd++){
v.clear();
push_v(next_);
if(IDA()){
printf("Case %d: %d\n",T,maxd);
break;
}
}
}
//print_time_;
return ;
}

  

UVA 11212 Editing a Book [迭代加深搜索IDA*]的更多相关文章

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

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

  2. Uva 11212 编辑书稿(迭代加深搜索)

    题意: 给定N个数的序列, 希望将它排列成1~N, 可以用剪切.粘贴来完成任务, 每次可以剪切一段连续的自然段, 粘贴时按照顺序粘贴. #include <bits/stdc++.h> # ...

  3. 埃及分数 迭代加深搜索 IDA*

    迭代加深搜索 IDA* 首先枚举当前选择的分数个数上限maxd,进行迭代加深 之后进行估价,假设当前分数之和为a,目标分数为b,当前考虑分数为1/c,那么如果1/c×(maxd - d)< a ...

  4. UVA 529 - Addition Chains,迭代加深搜索+剪枝

    Description An addition chain for n is an integer sequence  with the following four properties: a0 = ...

  5. UVA 1343 - The Rotation Game-[IDA*迭代加深搜索]

    解题思路: 这是紫书上的一道题,一开始笔者按照书上的思路采用状态空间搜索,想了很多办法优化可是仍然超时,时间消耗大的原因是主要是: 1)状态转移代价很大,一次需要向八个方向寻找: 2)哈希表更新频繁: ...

  6. BZOJ1085: [SCOI2005]骑士精神 [迭代加深搜索 IDA*]

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1800  Solved: 984[Submit][Statu ...

  7. 7-10Editing aBook uva11212(迭代加深搜索 IDA*)

    题意:  给出n( 2<=n<=9) 个乱序的数组  要求拍成升序  每次 剪切一段加上粘贴一段算一次  拍成1 2 3 4 ...n即可     求排序次数 典型的状态空间搜索问题   ...

  8. UVA - 1374 Power Calculus (dfs迭代加深搜索)

    题目: 输入正整数n(1≤n≤1000),问最少需要几次乘除法可以从x得到xn ?在计算过程中x的指数应当总是正整数. 思路: dfs枚举次数深搜 注意: 1.指数如果小于0,就退出当前的搜索 2.n ...

  9. UVa 1374 - Power Calculus——[迭代加深搜索、快速幂]

    解题思路: 这是一道以快速幂计算为原理的题,实际上也属于求最短路径的题目类型.那么我们可以以当前求出的幂的集合为状态,采用IDA*方法即可求解.问题的关键在于如何剪枝效率更高.笔者采用的剪枝方法是: ...

随机推荐

  1. MySQL用户管理+MySQL权限管理

    我们现在默认使用的都是root用户,超级管理员,拥有全部的权限! 但是,一个公司里面的数据库服务器上面可能同时运行着很多个项目的数据库! 所以,我们应该可以根据不同的项目建立不同的用户,分配不同的权限 ...

  2. R语言因子

    R语言因子 因子是它们用于将数据进行分类并将其存储为级别的数据对象.它们可以同时存储字符串和整数.它们在具有唯一值的有限数目的列是有用的. 例如,"male, "Female&qu ...

  3. day002--python编程的相关软件,变量

    --python是一门解释型语言,需要安装解释器,由于python3和python不兼容,所以需要安装这两个版本的解释器. 目前python2.7版本已经停止更新,使用企业较少,所以应当以学习pyth ...

  4. 显示调用dll

    原dll中导出的接口如图: Head.h: struct zint_render_line { float x, y, length, width; struct zint_render_line * ...

  5. java 使用poi导出Excel,设置单元格保护不可编辑

    //sheet表加密:等效excel的审阅菜单下的保护工作表 sheet.protectSheet(new String("333"));//333是密码 更多设置请参考:http ...

  6. day39-Spring 11-Spring的AOP:基于AspectJ的XML配置方式

    package cn.itcast.spring3.demo2; import org.aspectj.lang.ProceedingJoinPoint; /** * 切面类 * @author zh ...

  7. 一条SQL完成跨数据库实例Join查询

    背景 随着业务复杂程度的提高.数据规模的增长,越来越多的公司选择对其在线业务数据库进行垂直或水平拆分,甚至选择不同的数据库类型以满足其业务需求.原本在同一数据库实例里就能实现的SQL查询,现在需要跨多 ...

  8. 1-1.go开发工具安装

    (1) (2) bin:go的可执行文件 src:go的源代码 (3)安装开发工具 安装:goland-2018.1.1.exe 将.jar文件复制到工具的bin目录下   用记事本打开“goland ...

  9. DLA SQL分析函数:SQL语句审计与分析的利器

    1. 简介 Data Lake Analytics(https://www.aliyun.com/product/datalakeanalytics)最新release一组SQL内置函数,用来进行SQ ...

  10. SharpDX初学者教程第1部分:在Visual Studio 2013中设置SharpDX项目

    原文 http://www.johanfalk.eu/blog/sharpdx-tutorial-part-1-setting-up-a-sharpdx-project-in-visual-studi ...