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

相關文章
相關標籤/搜索