sicily1142(深搜加剪枝)

Posted sysu_zjl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sicily1142(深搜加剪枝)相关的知识,希望对你有一定的参考价值。

数据结构期末考试最后一道题,到现在才写出来哈。。
还是因为看了《编程之美》这本书一摞烙饼的排序问题之后才写的。
看完编程之美,才发现这道题原来这么坑。没有在多项式复杂度的解法。
然后我首先用编程之美类似的方法,导致time limit
《编程之美》书中的方法是先给定的upperbound为2*countn-1
当dfs之后有比upperbound小的再动态修改upperbound,
这样的方法,
对于数列长度小的
剪枝并不太明显,有可能需要全部穷举之后才有。
所以我就网上搜了下资料
http://blog.csdn.net/fanfank/article/details/8976905
他的解法给我很大的启发,
在数列长度小的数组
下界值(当前序列排序最少需要的次数)
循环1~n通过判断相邻数列是否为数列排序后也相邻,不相邻则sum++,得到下界值sum
这样每次dfs到达与下界值同样的深度或者通过预判(下界值+当前深度)超过下界值,就停止继续搜索进行剪枝,达到更快的效率
这道题跟编程之美的不同之处还在于其序列不是1~n而是n个绝对值不超过32767
所以下界值不是简单判断相邻数的差小于1或者-1而是判断排序后的索引是否相邻

#include <cstdio>
#include <algorithm>
using namespace std;
struct SortArray 
    int index;
    int x;
    friend bool operator< (const SortArray& a, const SortArray& b) 
        return a.x < b.x;
    
s[30], Array[30];
int max_swap;
int n;
//判断相邻值排序后是否相邻
int lowerbound(int n) 
    int sum = 0;
    for (int i = 1; i < n; i++) 
        if (Array[i].index - Array[i-1].index == 1 || Array[i].index - Array[i-1].index == -1)
            ;
        else
            sum++;
    
    return sum;

bool check(int n) 
    for (int i = 1; i < n; i++) 
        if (Array[i].x < Array[i-1].x)
            return false;
    
    return true;

void reverse(int end) 
    for (int i = 0; i <= end/2; i++)
        swap(Array[i], Array[end-i]);

bool dfs(int step) 
    if (lowerbound(n) > step)//进行预判,判断下界是否大于step,
        return false;
    if (check(n))
        return true;
    for (int i = 1; i < n; i++) //穷举可能的翻转
        reverse(i);
        if (dfs(step-1))
            return true;
        reverse(i);
    
    return false;

int main() 
    scanf("%d", &n);
    for (int i = 0; i < n; i++) 
        scanf("%d", &Array[i].x);
        s[i].x = Array[i].x;
        s[i].index = i;//记录该序列原始的索引
    
    sort(s, s+n);//对s进行排序
    for (int i = 0; i < n; i++) 
        Array[s[i].index].index = i;//通过s记录的索引,找回原来数组的值,并给其添加排序后的索引,方便判断相邻值排序后是否相邻
    
    int step = lowerbound(n);//下界,最少需要翻转的次数
    while (!dfs(step++));
    printf("%d\\n", step-1);
    return 0;

以上是关于sicily1142(深搜加剪枝)的主要内容,如果未能解决你的问题,请参考以下文章

解数独算法的实现——剪枝优化

Sicily 1153: 马的周游问题(DFS+剪枝)

POJ1011 (深搜+剪枝)

poj1190 生日蛋糕(深搜+剪枝)

深搜的剪枝技巧

深搜优化剪枝