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(深搜加剪枝)的主要内容,如果未能解决你的问题,请参考以下文章