關於 double sort 這道題的思考

聲明

   筆者最近意外的發現 筆者的我的網站 http://tiankonguse.com/ 的不少文章被其它網站轉載,可是轉載時未聲明文章來源或參考自 http://tiankonguse.com/ 網站,所以,筆者添加此條聲明。php

    鄭重聲明:這篇記錄《關於 double sort 這道題的思考》轉載自 http://tiankonguse.com/ 的這條記錄:http://tiankonguse.com/record/record.php?id=651git

 

前言

前言的前言github

昨天原本寫好了這篇記錄,可恨中間我出去打了一個電話,回來繼續寫,寫完我想到可能session已經失效,因此我新打開一個頁面,登陸,而後在這個頁面提交。返回了提交成功的標籤,可是跳轉到那篇文章時提示不存在。這個,我不能再忍受了,因而本身作了一個自動保存的功能。算法

 

首先今天寫的內容將會簡短,由於昨天寫的很久很久,結果自動保存功能尚未實現。不過如今,時刻都在自動保存着,不再用擔憂這個問題了。session

首先聲明這篇記錄不是解題報告,只是一場個人大腦裏思路的旅行。函數

 

前幾天學弟學妹們有一場比賽,學弟邀請我做爲技術支持者去幫忙,在那個過程當中我看了幾道題。網站

其中有兩道題正常比賽沒有其餘人提交,因而我研究了一下。隊列

研究的第一道就一個暴力dfs就能夠過,只是可能正常比賽沒人看懂題意,我看了好幾個小時纔看懂的。內存

第二道就是 double sort。開發

 

正文

題意

 

什麼是 double sort 呢?

就以題目中的講解例子來講說吧。

題目說對於一組數 [5; 4; 3; 2; 1], 若是隻能夠交換相鄰的數字,要使這組數達到升序至少須要 10 步。

這個很好理解,假設一個數字要和左面的數字交換,那只有一種狀況。

可是對於兩組數 [5,5; 4,4; 3,3; 2,2; 1,1] 來講,也是隻能交換相鄰的數字。這是一個數字和左面的數字交換時就有兩種狀況了。

好比對於 4 能夠和 第一個5交換,也能夠和第二個5交換。

目標是使這兩組數字達到升序。題意還說這個例子的答案是 15 ,不是 20.

 

而後,沒而後了。

 

錯誤的題意

看完上面的題意,我有一個疑問:難道真的是要排成 [5,5; 4,4; 3,3; 2,2; 1,1] 的樣子嗎? 15 步可能嗎?

因而我猜想多是達到每組升序便可,好比 [4,5; 4,5; 2,3; 2,3; 1,1], 這樣第一組是 [4; 4; 2; 2; 1], 第二組書[5; 5; 3; 3; 1].

因而我寫了一個暴力程序,第一組樣例還真跑出一個 15 的答案來。

可是第二組 答案大小比樣例少了1。

 

既然結果不正確,那就須要把那個正確的答案的路徑輸出來,看看有什麼不一樣。

結果發現最終答案應該是上下兩個的差不超過2.

因而我添加了一個 fix 函數,修正這種狀況。

而後三個樣例都過了。

再而後就是 WA 了。

 

正確的題意

而後我想仍是想弄明白題意再說,因而用 [3,3; 2,2; 1,1] 模擬了一下,發現真的比 [3; 2; 1] 的答案的二倍少。

這時我意識到可能目標真的是求[1,1; 2,2; 3,3]  這種狀況。

 

暴力DFS嘗試

知道了題意,數據量只是到8,因而寫了一個暴力程序。

使用 "1122334455" 串的形式map 了一下。

對於5瞬間跑出答案,對於6 跑了好一會。

 

雙向DFS搜索

直接搜太慢,那就雙向搜試試。

因而寫了一個雙向 DFS, 結果 6也是瞬間跑出來,可是 7 怎麼也出不來了。

 

使用逆序數剪枝雙向搜索

寫的雖然是雙向DFS,可是其實仍是暴力搜索,尚未加什麼剪枝。

因而使用 逆序數剪枝, 7 十秒多跑出來了。

因而提交試試,發現 超內存,如今不是時間問題了,是內存不夠的問題了。

 

狀態壓縮

內存不夠就要想法節省內存,其中 map<string, string>最浪費內存。

爲何要使用 string 呢?

爲了保存一個狀態。

那能不能使用位數壓縮狀態麼?

發現還真的能夠。

數字是從1-8,也就是0-7 了。最少須要三位才能表示一個數字,總共須要 24位數字,3字節,long long 類型的能夠。

因而修改爲map<LL, LL>.

爲何要使用 map 呢?

貌似是爲了記錄路徑,這裏不須要記錄路徑。

因而修改爲爲了 set<LL> .

再次提交仍是超內存。

 

A* 算法出世

究竟是爲何會超內存呢?

由於狀態太多了。

爲何狀態太多了呢?

由於咱們使用的暴力搜索,咱們不知道哪一個狀態是最優解,哪一個不是。

那能不能確認某個狀態必定比另外一個狀態更優呢?

貌似能夠的。

那就用優先隊列吧。

因而問問學弟小堆是使用大於號仍是小於號。最後本身在模板生找到了。

 

A*搜索的估價函數

雙向搜索時曾遇到過逆序數,因而使用逆序數做爲估價函數吧。

7 終於跑出來了。

可是 8 仍是跑步出來。

 

A*搜索的另外一個估價函數

逆序數這個估價函數行嗎?

貌似偏差太大,無效狀態太多。

那能不能換一個估價函數呢?

貌似還真有一個,每一個數字離本身最終的位置的距離也是一個不錯的估價汗是。

那就使用這個估價函數吧。

因而把估價函數換了換,結果仍是隻能跑出7來。

 

強強聯合

怎麼仍是跑不出 8 呢?

估價函數太弱,精度過低。

那能不能增強估價函數呢?

貌似能夠的。

好比說呢?

對於逆序數,交換一次最多減小3個逆序數,最少一個。

對於相對距離,交換一次最多減小兩個,最少不變。

知道了,就這個辦呢。

因而使用兩個估計函數,從新了程序,結果7確實跑的快樂,可是仍是跑不出8來。

 

總結

這道題雖然沒有跑出 8 來,可是收穫很多。

首先這一切都是本身獨立思考的,再次開發了智力。

有興趣的人能夠繼續思考下去,儘可能不要看解題報告。

全部代碼都在這裏 https://github.com/tiankonguse/ACM/tree/master/hust/doublesort

參考

tiankonguse 的模板

相關文章
相關標籤/搜索