uva11212

题目描述:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=23956

/*
solution:
    采用IDA*算法

note:
    IDA*算法就是从小到大枚举深度上限,每次执行只考虑最大深度之内的结点,再设计一个乐观估价函数,用来剪枝。
    其实就是 “迭代加深搜索” + "乐观函数剪枝"

date:
    2016/5/8
*/
#include 
#include 
#include 

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

你可能感兴趣的:(uva,OJ,=====各种搜索=====)