P2534 [AHOI2012]铁盘整理

考察:IDA*+离散化ios

这估价函数本蒟蒻彻底没想到....数组

思路:ide

      最少操做次数,若是用bfs须要存储数组.考虑一波IDA*,无需存储数组只须要回溯.可是估价函数很差想.参考了大佬的题解,原来须要离散化....将不一样的半径按大小映射为1~n之间的数字.目标就是让最终序列为1...n递增排序.能够发现,咱们每操做一次,就改变操做区间右端点与非操做区间左端点的大小关系.咱们能够发现最终序列a[i+1]-a[i] = 1.那么对于当前序列a[i+1]-a[i] != 1,res++.是否可行?函数

      答案是不可行.对于5 4 3 2 1.按上面的预估函数返回结果是4,实际操做数是1.那么延伸一下abs(a[i+1]-a[i])!=1,res++.是否可行.答案是可行,但咱们须要将a[n+1]设置为n+1才行.不然5 4 3 2 1返回0.spa

      这样的预估函数为何正确?对于a[l],a[l+1],若是它们之间的差不是1 or -1,那么就须要将前面的数换走,不然二者先后二者之差的绝对值不会改变.因此每个不为-1 or 1的差,至少须要1次翻转.排序

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 20;
 6 int r[N],n,b[N],deep;
 7 int h()
 8 {
 9     int res = 0;
10     for(int i=0;i<n;i++)
11       res+=(abs(r[i+1]-r[i])==1?0:1);
12     return res;
13 }
14 bool dfs(int depth,int pre)
15 {
16     int val = h();
17     if(val+depth>deep) return 0;
18     if(!val) return 1;
19     for(int i=2;i<=n;i++)
20     {
21         if(i==pre) continue;
22         reverse(r,r+i);
23         if(dfs(depth+1,i)) return 1;
24         reverse(r,r+i);
25     }
26     return 0;
27 }
28 int main()
29 {
30     scanf("%d",&n);
31     for(int i=0;i<n;i++) scanf("%d",&r[i]);
32     memcpy(b,r,sizeof r);
33     sort(b,b+n);
34     for(int i=0;i<n;i++)
35        r[i] = lower_bound(b,b+n,r[i])-b+1;
36     r[n] = n+1;
37     while(!dfs(0,-1)) deep++;
38     printf("%d\n",deep);
39     return 0;
40 }

 

总结:string

        IDA* h()函数常见操做:it

        1.不在位置上的数,res++io

        2.某次操做后,边界关系.class