uva11212(Editing a Book/编辑书稿)=>IDA*算法/经典的估价函数

题意:将一个数字序列以最少的剪切次数粘贴成另一个数字序列。

解析:本题可用IDA*,也就是设计了估价函数的迭代加深搜索。

IDA*大体上指的是,首先将初始状态结点的H值设为阈值maxH,然后进行深度优先搜索,搜索过程中忽略所有H值大于maxH的结点;如果没有找到解,则加大阈值maxH,再重复上述搜索,直到找到一个解。其中IDA*的减枝策略,每遍历一个深度的时候,进行判断:

当前局面的估价函数值 + 当前深度 > 预定义最大搜索深度

原因是:最坏的情况是需要n-1次剪切,搜索层数不多,但每一层的状态数目又非常庞大,所以适宜使用IDA*。考虑每一个序列后续不正确的数字个数h,每一次剪切最多3个数字后续数字发生改变,每次剪切最多可减少3个不正确的后续数字。所以在当前层d,最大层maxd时,最多可减少的不正确后续数字是3*(maxd-d),若h>3*(maxd-d),则剪枝。

下面进行这道题的减枝的分析(也叫做启发函数),当你改变一个区间的位置,你会改变3个数的位置的正确性

比如 1,2,3,4,5,6.序列,你把2,3移动到6后面,那么1的后面变成了5, 而 6的后面编程了2,而3的后面变成 空了,所以每次移动一个区间,最多可以改变3个数的正确性,也就是说,对于这道题如果遍历到了一个深度, (还能遍历的深度 - 当前深度) *3< 不正确数字的个数,那么就没有必要继续遍历了,因为往后你就是全把这些数字该对了也无法达到理想状态。

代码如下:

#include 
#include 
#include 
#include 
using namespace std;
const int maxn = 10;
int n,a[maxn];
int is_sorted(){
for(int i=1;i<=n;i++) if(a[i]!=i) return false;
return true;
}
inline int h(){
int cnt=0;
for(int i=1;i3*maxd) return false;//估价函数
if(is_sorted()) return true;

int olda[maxn],b[maxn];
for(int i=1;i<=n;i++) olda[i]=a[i];//需要另一个数组来保存原来的数组

for(int i=1;i<=n;i++)//枚举起始点
  for(int j=i;j<=n;j++){//枚举终止点
 //剪切
    int cnt=1;
    for(int k=1;k<=n;k++) if(kj) b[cnt++]=olda[k];
   //在K前插入
    for(int k=0;k



你可能感兴趣的:(暴力)