UVa 11212 – Editing a Book [IDA*]

本题的关键是应用IDA*算法,降低时间复杂度,启发函数的发现和推导是重点。

对于可以用回溯法求解但解答树的深度没有明显上限的题目,可以考虑使用迭代加深搜索。设计一个乐观估计函数,预测从当前节点至少还学要扩展几层才有可能得到解,则状态空间搜索变成了IDA*算法。

刚开始吧状态定义为typedef  int  State[12],但后来发现编译器老是报错并且极易出现各种错误,索性直接定义为一个struct。

#include <bits/stdc++.h>
using namespace std;

struct State{
    int a[12];
};
int n, kase = 0, maxd;

int getH(State cur)
{
    int cnt = 0;
    for(int i = 0; i < n-1; ++i)
        if(cur.a[i]+1 != cur.a[i+1])
            cnt++;
    return cnt;
}
bool DFS(int d, State u)
{
    int H = getH(u);
    if(d == maxd) return H == 0;
    if(3*d + H > 3*maxd) return false;
    for(int x = 0; x < n - 1; ++x)
        for(int l = 1; l <= x+1; ++l)
            for(int r = 1; r <= n-x-1; ++r){
                State v; memcpy(v.a, u.a, sizeof(u.a));
                for(int i = x - l + 1, j = x + r - l + 1; i <= x; ++i, ++j)
                    v.a[j] = u.a[i];
                for(int i = x + 1, j = x - l + 1; i <= x + r; ++i, ++j)
                    v.a[j] = u.a[i];
                if(DFS(d + 1, v)) return true;
            }
    return false;
}
int main()
{
    ios::sync_with_stdio(false);
    while(cin >> n && n){
        State beg;
        for(int i = 0; i < n; ++i)
            cin >> beg.a[i];
        for(maxd = 0; ; ++maxd)
            if(DFS(0, beg))
                break;
        printf("Case %d: %d\n", ++kase, maxd);
    }
    return 0;
}

欢迎留言