UVa11212 Editing a Book (IDA*)

链接:http://acm.hust.edu.cn/vjudge/problem/23956分析:IDA*,设计一个乐观估价函数,由于每次剪切h最多减少3,因为最多有三个数字的后继数字发生了改变,DFS时用two pointers枚举要移动的数字串和移动到的位置然后递归枚举,直至不满足乐观估价函数或找到解后成功返回,从小到大枚举的深度上限maxd即为最少移动次数。
 1 #include <cstdio>
 2 #include <cstring>
 3
 4 const int maxn = 9;
 5
 6 int n, a[maxn];
 7
 8 bool is_sorted() {
 9     for (int i = 0; i < n - 1; i++)
10         if (a[i] >= a[i + 1]) return false;
11     return true;
12 }
13
14 int h() {
15     int cnt = 0;
16     for (int i = 0; i < n - 1; i++)
17         if (a[i] + 1 != a[i + 1]) cnt++;
18     if (a[n - 1] != n) cnt++;
19     return cnt;
20 }
21
22 bool dfs(int d, int maxd) {
23     if (d * 3 + h() > maxd * 3) return false;
24     if (is_sorted()) return true;
25     int b[maxn], olda[maxn];
26     memcpy(olda, a, sizeof(a));
27     for (int i = 0; i < n; i++)
28         for (int j = i; j < n; j++) {
29             int cnt = 0;
30             for (int k = 0; k < n; k++)
31                 if (k < i || k > j) b[cnt++] = olda[k];
32             for (int k = 0; k <= cnt; k++) {
33                 int cnt2 = 0;
34                 for (int p = 0; p < k; p++) a[cnt2++] = b[p];
35                 for (int p = i; p <= j; p++) a[cnt2++] = olda[p];
36                 for (int p = k; p < cnt; p++) a[cnt2++] = b[p];
37                 if (dfs(d + 1, maxd)) return true;
38             }
39         }
40     return false;
41 }
42
43 int solve() {
44     for (int maxd = 0; ; maxd++)
45         if (dfs(0, maxd)) return maxd;
46 }
47
48 int main() {
49     int kase = 0;
50     while (scanf("%d", &n) == 1 && n) {
51         for (int i = 0; i < n; i++) scanf("%d", &a[i]);
52         printf("Case %d: %d\n", ++kase, solve());
53     }
54     return 0;
55 }
时间: 2024-11-05 02:28:22

UVa11212 Editing a Book (IDA*)的相关文章

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

题意:你有一篇n(2≤n≤9)个自然段组成的文章,希望将它们排列成1,2,-,n.可以用Ctrl+X(剪切)和Ctrl+V(粘贴)快捷键来完成任务.每次可以剪切一段连续的自然段,粘贴时按照顺序粘贴.注意,剪贴板只有一个,所以不能连续剪切两次,只能剪切和粘贴交替.例如,为了将{2,4,1,5,3,6}变为升序,可以剪切1将其放到2前,然后剪切3将其放到4前.再如,排列{3,4,5,1,2},只需一次剪切和一次粘贴即可--将{3,4,5}放在{1,2}后,或者将{1,2}放在{3,4,5}前. 分析

UVa11212 - Editing a Book

#include<iostream> #include<cstdio> #include<cstring> using namespace std; class Board { public: int a[16]; int h; int n; bool readIn() { int i; scanf("%d",&n); if(n == 0) return false; for(i=0;i<n;i++) scanf("%d&qu

【Uva11212】 Editing a Book(IDA*)

[题意] 有n个数字的全排列,每次可以剪切一段粘贴到某个位置.问最后变成升序最少多少步. 如"{2,4,1,5,3,6}要2步 {3,4,5,1,2}只要一步 [分析] 迭代深搜真的AC了也觉得慌= = [其实看到这题不应该想到宽搜么??? 全排列只有9!=362880个 这题的IDA*的估价函数特别机智: n<=9,最多2需要8步,深度上限为8. 考虑后继不正确的赎回自个数h,可以证明每次剪切时候h最多减少3,因此当3*d+h>3*maxd时可以剪枝. [证明上面那个画一下就知道,

UVa11212,Editing a Book

正如书上所说,本题需要用IDA*算法求解 启发函数是3d+h>3maxd(d为当前操作步骤数,h为当前逆序对数,maxd为当前枚举的最大步骤数) 可见迭代递归的核心思想是枚举ans去dfs是否可行,相反常规搜索是dfs去需找ans. 一开始卡在状态图的转移与回溯上,参考(http://blog.csdn.net/sssogs/article/details/8836606)大神的代码后得到启发,可以将图或是表直接写成结构体或是类跟着递归走(当然,图或是表不能很大,比较大的话应该还是用回溯比较好吧

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

迭代加深搜索 自己看的时候第一遍更本就看不懂..是很水,但智商捉急也是没有办法的事情. 好在有几个同学已经是做过了这道题并且对迭代加深搜索的思路有了一定的了解,所以在某些不理解的地方询问了一下他们的见解, 真的是很有帮助,也许自己想要想很久才能想明白,还会很痛苦,稍微问一下别人的想法,点上一个方向,剩下的自己就能想得明白了. 迭代加深. 把answer(需要的步数或其他)在主函数里面从零往上递加,此之谓 "层数",亦可谓之"深度".用书上的话就是: 从小到大枚举深度

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 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

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 ; 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,

IDA*搜索简介与其他搜索方式的简单对比 UVA11212 EditingaBook

首先说说IDS,就DFS限定一个层数上限maxd,如果在maxd范围内没有找到解,就增加maxd,继续搜索. 当访问到当前结点u时,估计还要搜索h(u)层,如果h(u)+当前层数d>maxd的时候就剪枝,这就是IDA*. IDA*属于DFS,当状态空间某一层的结点数无穷大时,BFS失效,只能DFS. 相比BFS,它的空间占用少(不需要判重复),时间效率也不低. 注意:A*的关键在于选取估价函数h(). ----------------------------------分割线----------

【UVa】11212 Editing a Book(IDA*)

题目 题目 ? ? 分析 get一下IDA*的技巧,感觉总体来说不难,主要是剪枝比较难想. 这是lrj的代码,比较通俗易懂,关键就是选定一个区间再取出来,插入到一个位置,接下来转移到这个状态. ? ? 代码 #include <bits/stdc++.h> using namespace std; const int maxn=10; int n,a[maxn]; bool is_sorted() { for(int i=0;i<n-1;i++) if(a[i]>=a[i+1])