- 迭代加深,逐层计算。
- 乐观估价函数,剪枝。
- 递归枚举,利用数组保存数据,之后恢复。
- 剪切一个片段并粘贴,最多改变3个后缀。
- 迭代加深的基本框架。
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=23956
框架:
is_success()//是否成功
h()//估价函数,用于剪枝
dfs()//遍历
{
is_success();
h();//利用h()判断是否应该剪枝
for()//递归枚举
{
保存目前状态。
递归枚举深入。
恢复状态。//可以利用memcpy()高效复制
}
}
solve()//迭代加深基本框架
{
if(is_success)//有时可以不用此判断。
int max_ans;//可能的最深
for(maxd = 0;;maxd++)
{
if(dfs(0,maxd))
return maxd;
}
return max_ans;
}
此题的标准代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 10;
int n, book[maxn];
bool is_goal() {//判断是否成功
bool ok = true;
for(int i = 0; i < n; i++) {
if(book[i] != i + 1) {
ok = false;
break;
}
}
return ok;
}
int h() {//判断一共有几个移动的小片段
int cnt = 0;
for(int i = 0; i < n - 1; i++) {
if(book[i] + 1 != book[i + 1])
cnt++;
}
if(book[n - 1] != n) cnt++;
return cnt;
}
bool dfs(int d, int maxd) {
if(3 * d + h() > maxd * 3) return false; //剪枝,因为移动一个片段最多改变三个后缀
if(is_goal()) return true;
//扩展节点同时进行加深搜索
int old_book[maxn]; //因为扩展节点后book会随之改变,为了保存原来的book
int past_to[maxn]; //保存要剪切后的部分
for(int i = 0; i < n; i++)
for(int j = i; j < n; j++) { //依次枚举要剪切的部分,i是左端开头,j是右端结尾
memcpy(old_book, book, sizeof(book)); //保存原来book
int cnt = 0;
for(int k = 0; k < n; k++)
if(k < i || k > j)
past_to[cnt++] = book[k]; //剪切后的部分
for(int k = 0; k <= cnt; k++) { //依次枚举要插入第k位置前面
int cnt2 = 0; //执行粘贴操作
for(int p = 0; p < k; p++) book[cnt2++] = past_to[p];
for(int p = i; p <= j; p++) book[cnt2++] = old_book[p];
for(int p = k; p < cnt; p++) book[cnt2++] = past_to[p];
if(dfs(d + 1, maxd)) return true; //加深搜索
memcpy(book, old_book, sizeof(old_book)); //如果加深搜索失败的话就返回原来的数组状态
}//枚举了每一种情况,并在结束恢复状态。
}
return false;
}
int solve() {//迭代加深基本模板
if(is_goal()) return 0;
for(int maxd = 0; maxd < 9; maxd++) //枚举层数,最多不超过9层dfs即可求出答案
if(dfs(0, maxd)) return maxd;
return -1;
}
int main()
{
//freopen("input.txt", "r", stdin);
int kase = 0;
while(~scanf("%d", &n) && n) {
memset(book, 0, sizeof(book));
for(int i = 0; i < n; i++) scanf("%d", &book[i]);
printf("Case %d: %d\n", ++kase, solve());
}
return 0;
}
在林伏案的博客上加了一些修改,代码来自http://blog.csdn.net/qq_29169749/article/details/51419907