POJ 1033 磁碟檔案片段整理 類比題 棧應用

來源:互聯網
上載者:User

以後一定要細心,不能再犯這個低級的錯誤,把WA控制在最低範圍內

參考了 http://www.cnblogs.com/damacheng/archive/2010/09/24/1833983.html的題目分析

題目大意:你要寫一個OS,要實現磁碟磁碟重組的功能。磁碟分為N個簇,一個檔案可以佔用K個簇,(1 <= K < N <= 10000),給出各個檔案的佔用磁碟的情況,也就是一個檔案佔用了哪些簇,想要進行磁碟重組,就是把這些簇按順序整理到磁碟的最頂部,例如給出樣本:

  檔案1:2 3 11 12,佔用了4個簇,編號為1-4。
  檔案2:7,佔用了1個簇,編號為5。

  檔案3:18 5 10,佔用了3個簇,編號為6-8。

  初始狀態是這樣的,0表示未佔用:

  簇號:  1  2  3  4  5  6  7  8  9 10  11  12  13  14  15  16  17  18

  邏輯編號:0  1  2  0  7  0  5  0 0   8   3   4   0  0   0   0   0   6 

  一共整理到最後,磁碟的情況最後是這樣的:

  簇號:  1  2  3  4  5  6  7  8  9 10  11  12  13  14  15  16  17  18

  邏輯編號:1  2  3  4  5  6  7  8 0   0   0   0  0   0   0   0  0   0 

  寫一個程式得到整理好片段最少需要多少步操作,並把這些操作列印出來。比如說第1個簇的內容放到第2個簇,列印出1 2。操作的定義是這樣的:把一個簇的內容放到另個一個簇中,算是一步操作。

  注意這裡是Special Judge,意思是只要答案符合要求就行了,不必和SAMPLE中的OUTPUT一樣也可以AC。

  怎麼才能找到最少的步數呢?我想了半天也沒怎麼想出來,於是看了看DISCUSS,總結以下:

  遍曆整個磁碟,設i為當前遍曆的簇的編號,clusters為整個磁碟,clusters[i]表示第i個簇是否被佔用,被哪個編號的檔案片段佔據。

  (1) 如果clusters[i]為0,也就是未被使用,不進行處理。

  (2) 如果clusters[i]為i,也就是已經到了整理好的狀態,不進行處理。

  (3) 如果clusters[i]不滿足1和2,則又有兩種情況。

    情況一:磁碟使用方式成鏈::

    簇號:  1  2  3  4  5  6 ...    

    邏輯編號:5  0  4  2  3  0 ...

    第1個簇被第5個檔案片斷佔據,第5個簇又被第3個檔案片段佔據,第3個簇又被第4個檔案片段佔據,第4個簇又被第2個檔案片斷佔據,第2個簇未被佔據。演算法就很簡單了,按照簇被訪問的反方向:

    clusters[2] = clusters[4],clusters[4] = clusters[3],clusters[3] = clusters[5],

    clusters[5] = clusters[1],最後clusters[1] = 0。怎麼樣反方向呢,使用一個棧就好了。

    情況二:磁碟使用方式成環::

    簇號:  1  2  3  4  5  6 ...    

    邏輯編號:5  1  4  2  3  0 ...

    這種情況跟情況一差不多,只是最後clusters[2]指向了第1個簇,這樣就形成了一個環,這裡只是需要額外處理一下,就像交換2個變數一樣,先在從磁碟末尾找到1個空的簇,因為題目保證至少有一個空的簇,先把clusters[2]放到這個空的簇中,然後再執行情況1中的操作,最後再把空的簇的值賦給clusters[1]就好了。最後注意一點,如果操作次數為0,則需要輸出一行資訊。

Source Code

Problem: 1033   User:
yangliuACMer
Memory: 420K   Time: 704MS
Language: C++   Result: Accepted
#include <iostream>#include <stack>using namespace std;int clusters[10001];int clusters_num, file_num;int counter = 1, move_num = 0;//檔案片段的其實編號和操作的總數int next, i, j, t, n;stack<int> s;void deal(){while(!s.empty()){t = s.top();cout<<t<<" "<<next<<endl;clusters[next] = clusters[t];next = t;s.pop();move_num++;}}void work(){for(i = 1; i <= clusters_num; i++){if(clusters[i] == i){//剛好放在了目標位置,無需移動continue;}else if(clusters[i] != 0){s.push(i);next = clusters[i];bool is_circled = false;//下面判斷是否出現了環while(true){if(clusters[next] == i){is_circled = true;break;} else if(clusters[next] == 0){is_circled = false;break;}s.push(next);next = clusters[next];//有用數組模仿鏈表的思想}if(is_circled == true){//有環的情況for(j = clusters_num; j >=0; j--){if(clusters[j] == 0) break;//從後向前找一個空位置,為解開環做準備}cout<<next<<" "<<j<<endl;clusters[j] = clusters[next];deal();clusters[next] = clusters[j];//把開始的結點移動回去clusters[j] = 0;cout<<j<<" "<<next<<endl;} else {//沒有環的情況deal();clusters[next] = 0;}}}if(move_num == 0) cout<<"No optimization needed"<<endl;//開始因為輸出格式中needed寫成need 而WA一次,太粗心了!!!}int main(){cin>>clusters_num>>file_num;for(i = 0; i < file_num; i++){cin>>n;for(j = 0; j < n; j++){cin>>t;clusters[t] = counter++;}}work();return 0;}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.