筆者最近意外的發現 筆者的我的網站 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] 這種狀況。
知道了題意,數據量只是到8,因而寫了一個暴力程序。
使用 "1122334455" 串的形式map 了一下。
對於5瞬間跑出答案,對於6 跑了好一會。
直接搜太慢,那就雙向搜試試。
因而寫了一個雙向 DFS, 結果 6也是瞬間跑出來,可是 7 怎麼也出不來了。
寫的雖然是雙向DFS,可是其實仍是暴力搜索,尚未加什麼剪枝。
因而使用 逆序數剪枝, 7 十秒多跑出來了。
因而提交試試,發現 超內存,如今不是時間問題了,是內存不夠的問題了。
內存不夠就要想法節省內存,其中 map<string, string>最浪費內存。
爲何要使用 string 呢?
爲了保存一個狀態。
那能不能使用位數壓縮狀態麼?
發現還真的能夠。
數字是從1-8,也就是0-7 了。最少須要三位才能表示一個數字,總共須要 24位數字,3字節,long long 類型的能夠。
因而修改爲map<LL, LL>.
爲何要使用 map 呢?
貌似是爲了記錄路徑,這裏不須要記錄路徑。
因而修改爲爲了 set<LL> .
再次提交仍是超內存。
究竟是爲何會超內存呢?
由於狀態太多了。
爲何狀態太多了呢?
由於咱們使用的暴力搜索,咱們不知道哪一個狀態是最優解,哪一個不是。
那能不能確認某個狀態必定比另外一個狀態更優呢?
貌似能夠的。
那就用優先隊列吧。
因而問問學弟小堆是使用大於號仍是小於號。最後本身在模板生找到了。
雙向搜索時曾遇到過逆序數,因而使用逆序數做爲估價函數吧。
7 終於跑出來了。
可是 8 仍是跑步出來。
逆序數這個估價函數行嗎?
貌似偏差太大,無效狀態太多。
那能不能換一個估價函數呢?
貌似還真有一個,每一個數字離本身最終的位置的距離也是一個不錯的估價汗是。
那就使用這個估價函數吧。
因而把估價函數換了換,結果仍是隻能跑出7來。
怎麼仍是跑不出 8 呢?
估價函數太弱,精度過低。
那能不能增強估價函數呢?
貌似能夠的。
好比說呢?
對於逆序數,交換一次最多減小3個逆序數,最少一個。
對於相對距離,交換一次最多減小兩個,最少不變。
知道了,就這個辦呢。
因而使用兩個估計函數,從新了程序,結果7確實跑的快樂,可是仍是跑不出8來。
這道題雖然沒有跑出 8 來,可是收穫很多。
首先這一切都是本身獨立思考的,再次開發了智力。
有興趣的人能夠繼續思考下去,儘可能不要看解題報告。
全部代碼都在這裏 https://github.com/tiankonguse/ACM/tree/master/hust/doublesort