考察: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