zoukankan      html  css  js  c++  java
  • poj 1033 Defragment

    题解转自: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,则需要输出一行信息。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<string>
      6 #include<queue>
      7 #include<algorithm>
      8 #include<map>
      9 #include<iomanip>
     10 #include<climits>
     11 #include<string.h>
     12 #include<numeric>
     13 #include<cmath>
     14 #include<stdlib.h>
     15 #include<vector>
     16 #include<stack>
     17 #include<set>
     18 #define FOR(x, b, e)  for(int x=b;x<=(e);x++)
     19 #define REP(x, n)     for(int x=0;x<(n);x++)
     20 #define INF 1e7
     21 #define MAXN 100010
     22 #define maxn 1000010
     23 #define Mod 1000007
     24 #define N 1010
     25 using namespace std;
     26 typedef long long LL;
     27 
     28 int n, m;
     29 int c[10010];
     30 int tmp;
     31 int k;
     32 int num;
     33 
     34 void gao()
     35 {
     36     int next;
     37     num = 0;
     38     stack<int> s;
     39     for (int i = 1; i <= n; ++i) {
     40         if (c[i] == i || c[i] == 0) continue;
     41         s.push(i);
     42         next = c[i];
     43         bool is_circle = false;
     44         while (true) {
     45             if (c[next] == i) {    //比如3放5 5放3,形成了一个环
     46                 is_circle = true;
     47                 break;
     48             }
     49             else if (c[next] == 0) {
     50                 is_circle = false;
     51                 break;
     52             }
     53             s.push(next);
     54             next = c[next];
     55         }
     56         int j;
     57         if (is_circle == true) {
     58             for (j = n; j >= 1; --j)
     59                 if (c[j] == 0) break;
     60             printf("%d %d
    ", next, j);
     61             c[j] = c[next];
     62             while (!s.empty()) {
     63                 int t = s.top();
     64                 s.pop();
     65                 printf("%d %d
    ",t,next);
     66                 c[next] = c[t];
     67                 next = t;
     68                 num++;
     69             }
     70             c[next] = c[j];
     71             c[j] = 0;
     72             printf("%d %d
    ", j, next);
     73         }
     74         else {
     75             while (!s.empty()) {
     76                 int t = s.top();
     77                 s.pop();
     78                 printf("%d %d
    ", t, next);
     79                 c[next] = c[t];
     80                 next = t;
     81                 num++;
     82             }
     83             c[next] = 0;
     84         }
     85     }
     86     if (num == 0) puts("No optimization needed");
     87 }
     88 
     89 int main()
     90 {
     91     int tt;
     92     cin >> n >> m;
     93         k = 1;
     94     for (int i = 0; i < m; ++i) {
     95         cin >> tmp;
     96         for (int i = 0; i < tmp; ++i) {
     97             cin >> tt;
     98             c[tt] = k++;
     99         }
    100     }
    101     gao();
    102     return 0;
    103 }
  • 相关阅读:
    卫星时间同步装置的安装及售后
    windowsU盘重装系统:操作流程
    vue安装正确流程
    win10以太网未识别的网络
    [UnityShader]unity中2D Sprite显示阴影和接受阴影
    [UnityShader]说厌了的遮挡显示
    [Unity]利用Mesh绘制简单的可被遮挡,可以探测的攻击指示器
    ConcurrentHashMap源码解读
    Vector底层原理
    LinkedList集合底层原理
  • 原文地址:https://www.cnblogs.com/usedrosee/p/4375187.html
Copyright © 2011-2022 走看看