UVa 11212 编辑书稿(dfs+IDA*)
2017-01-23 20:57
405 查看
https://vjudge.net/problem/UVA-11212
题意:给出n个自然段组成的文章,将他们排列成1,2...,n。每次只能剪切一段连续的自然段,粘贴时按照顺序粘贴。
思路:状态空间的搜索问题。
首先介绍一下IDA*,它属于DFS,在DFS遍历的时候,设定一个深度上限maxd,当前结点n的深度为g(n),乐观估价函数为h(n),则当g(n)+h(n)>maxd时应 该剪枝。这样的算法就是IDA*。
在这道题目中,由于最多就9个数,所以最多只需要剪切8次肯定是可以完成升序排列的。所以最大深度可以从1开始一直到8,依次去寻找是否能成功。
在这题中最重要的剪枝就是考虑后继不正确的数字个数h,可以证明每次剪切时h最多减少3,因此如果3*(maxd-d)<h,则可以直接剪枝。因为此时即使一直遍历到限定深 度maxd,也无法将h的个数减为0。另外也还有许多地方可以剪枝,下面的代码中我有仔细介绍。
题意:给出n个自然段组成的文章,将他们排列成1,2...,n。每次只能剪切一段连续的自然段,粘贴时按照顺序粘贴。
思路:状态空间的搜索问题。
首先介绍一下IDA*,它属于DFS,在DFS遍历的时候,设定一个深度上限maxd,当前结点n的深度为g(n),乐观估价函数为h(n),则当g(n)+h(n)>maxd时应 该剪枝。这样的算法就是IDA*。
在这道题目中,由于最多就9个数,所以最多只需要剪切8次肯定是可以完成升序排列的。所以最大深度可以从1开始一直到8,依次去寻找是否能成功。
在这题中最重要的剪枝就是考虑后继不正确的数字个数h,可以证明每次剪切时h最多减少3,因此如果3*(maxd-d)<h,则可以直接剪枝。因为此时即使一直遍历到限定深 度maxd,也无法将h的个数减为0。另外也还有许多地方可以剪枝,下面的代码中我有仔细介绍。
#include<iostream> #include<string> #include<cstring> using namespace std; int n; int a[12]; bool goal() //判断是否已达到最终状态 { for (int i = 0; i < n - 1; i++) { if (a[i]>a[i + 1]) return false; } return true; } int h() //计算后继不正确的个数 { int number = 0; for (int i = 0; i < n-1; i++) { if (a[i + 1] != a[i] + 1) number++; } if (a[n - 1] != n) number++; return number; } bool dfs(int d, int maxd) { if (3 * d + h()>3 * maxd) return false; //剪枝 if (goal()) return true; int pre[12]; //保存原来序列 int cut[12]; //保存剪切后的序列 for (int i = 0; i < n; i++) //枚举,i为剪切起点,j为剪切终点 { if (i == 0 || a[i] != a[i - 1]+1) //剪枝,不破坏连续的数字片段 { for (int j = i; j < n; j++) { while (a[j + 1] == a[j] + 1) j++; //剪枝,如果一个数字片段已经连续,则不要去破坏它 memcpy(pre, a, sizeof(a)); int cnt = 0; for (int k = 0; k < n; k++) //保存剪切后的序号 { if (k<i || k>j) cut[cnt++] = a[k]; } for (int k = 0; k <= cnt; k++) //枚举,依次插入到第k个位置之前 { int cnt2 = 0; for (int t = 0; t < k; t++) a[cnt2++] = cut[t]; for (int t = i; t <= j; t++) a[cnt2++] = pre[t]; for (int t = k; t < cnt; t++) a[cnt2++] = cut[t]; if (dfs(d + 1, maxd)) return true; //继续深搜 memcpy(a, pre, sizeof(pre)); //如果失败,则恢复a[]的原来的数字片段 } } } } return false; } int solve() { if (goal()) return 0; for (int i = 1; i < 9; i++) //最多只需要进行8次dfs即可获得最终状态 { if (dfs(0, i)) return i; } } int main() { //freopen("D:\\txt.txt", "r", stdin); int kase = 0; while (cin >> n && n) { memset(a, 0, sizeof(a)); for (int i = 0; i < n; i++) cin >> a[i]; int ans=solve(); cout << "Case " << ++kase << ": " << ans << endl; } }
相关文章推荐
- 搜索·IDA*·UVA11212 编辑书稿
- 例题 7-10 编辑书稿 UVa 11212
- uva11212 编辑书稿 迭代加深
- Editing a Book UVA - 11212(DFS+IDA*)
- IDA*,迭代加深搜索(编辑书稿,uva 11212)
- UVa 11212 Editing a Book (编辑书稿)迭代加深
- 例题7-10 编辑书稿(Editing a Book, UVa 11212)
- UVa11212 编辑书稿(Editing a book)
- uva 11212 - Editing a Book(迭代加深搜索 IDA*) 迭代加深搜索
- 迭代加深搜索--IDA*--uva11212 Editing a book
- uva 11212 - Editing a Book(迭代加深搜索 IDA*) 迭代加深搜索
- uva-11212-IDA*
- UVA - 11212 Editing a Book(迭代加深搜索 IDA* + 模板)
- UVa 1343 旋转游戏(dfs+IDA*)
- UVA 11212 IDA*
- Editing a Book UVA - 11212 IDA*
- UVA 11212 IDA*
- 例题7-10 UVA 11212 Editing a Book (IDA*搜索)
- UVa 11212:Editing a Book(IDA*)
- UVa 1374 快速幂计算(dfs+IDA*)