zoukankan      html  css  js  c++  java
  • POJ 3460 Booksort(IDA* + 估价函数设计)

    题意:

    有N(1 ≤ N ≤ 15)本书,每本与每本的高度都不一样。现在可以按照以下的办法整理书:抽出一摞书,再保持原来的顺序插进一个位置。

    这样的话我们称之为“一次操作”。现在你需要求出至少需要经过几次操作才能让书变成按高度升序的状态。如果需要5次或者多于5次,只需要输出“5 or more”。

    思路:

    1. 题目中已经有个很明显的提示:最多不超过 5 次。于是便可以用 IDA* + 暴力枚举试图去解决问题;

    2. IDA* 不难,暴力也不难,难的是如果根据状态设计启发式函数:由于每次操作,最多能改变 3 个元素的后继,所以根据这个信息点来设计启发式函数能满足要求;

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    int books[20], N;
    
    void swapbooks(int p, int x, int q) {
        int buffer[20], c = 0;
        for (int i = x + 1; i <= q; i++)
            buffer[c++] = books[i];
        for (int i = p; i <= x; i++)
            buffer[c++] = books[i];
        for (int i = p; i <= q; i++)
            books[i] = buffer[i-p];
    }
    
    int getdiff() {
        int h = 0;
        for (int i = 0; i < N - 1; i++) {
            if (books[i] + 1 != books[i+1])
                h += 1;
        }
        if (books[N-1] != N)
            h += 1;
        return (h + 2) / 3;
    }
    
    int maxdepth;
    bool succ;
    
    int dfs(int depth) {
        int h = getdiff();
        if (h == 0) {
            succ = true;
            return depth;
        }
        int f = depth + h;
        if (f > maxdepth)
            return f;
    
        int newbound = 1e9;
        for (int p = 1; p < N; p++) {
            for (int i = 0, j = i + p; j < N; i++, j++) {
                for (int k = i; k < j; k++) {
                    swapbooks(i, k, j);
                    int f = dfs(depth + 1);
                    if (succ)
                        return f;
                    newbound = min(f, newbound);
                    swapbooks(i, i + j - k - 1, j);
                }
            }
        }
        return newbound;
    }
    
    int main() {
        int cases;
        scanf("%d", &cases);
        while (cases--) {
            scanf("%d", &N);
            for (int i = 0; i < N; i++)
                scanf("%d", &books[i]);
    
            maxdepth = getdiff();
            if (maxdepth)
                succ = false;
            else
                succ = true;
            while (!succ && maxdepth < 5) 
                maxdepth = dfs(0);
    
            if (!succ)
                printf("5 or more\n");
            else
                printf("%d\n", maxdepth);
        }
        return 0;
    }
  • 相关阅读:
    基于Metaweblog API 接口一键发布到国内外主流博客平台
    uva144 Student Grants
    Uva 10452
    Uva 439 Knight Moves
    Uva 352 The Seasonal War
    switch语句
    java——基础知识
    我的lua学习2
    codeforces 431 D. Random Task 组合数学
    codeforces 285 D. Permutation Sum 状压 dfs打表
  • 原文地址:https://www.cnblogs.com/kedebug/p/2994282.html
Copyright © 2011-2022 走看看