题目来源:http://poj.org/problem?id=1033

题目大意:

  某操作系统的文件系统中,所有的磁盘空间被分为N个大小相等的cluster,编号1至N。每个文件占用一个或多个cluster。所有没有被文件占用的cluster称为是空闲的。磁盘上的一个文件如果放置在连续的cluster上,读取速度是最快的。

  磁盘以匀速旋转,磁头找到某一个cluster的时间的不等的。因此,找到靠近开头的cluster更快。所有的文件被事先按访问频率高到低编号1到K,最好的文件放置方式是:文件1放置于cluster 1,2,...S1,文件2放置于cluster S1+1, S1+2,...S1+S2.后面类似,紧挨着放置。Si表示第i个文件占据的cluster数。

  为了将磁盘上的文件整理成上述的最优放置方式,需要对cluster进行移动。一次移动包括将一个cluster的内容读出来,写至一块空闲的cluster上,完成后之前的那块cluster变为空闲。

  程序的目标是将磁盘上的文件变为最优放置方式需要的最少移动次数和移动次序。

输入:第一行含两个整数N和K分别代表cluster数和文件数。接下来K行,每行代表一个文件,第一个数字代表该文件含多少cluster,后面的每个数字代表所占的cluster的编号。

输出:按顺序输出表示移动的数据对Pj,Qj。表示将Pj号cluster的数据移动到Qj.(答案可能不唯一,采用了Special Judge,只要答案正确即可)不需要移动则输出"No optimization needed".


Sample Input

20 3
4 2 3 11 12
1 7
3 18 5 10

Sample Output

2 1
3 2
11 3
12 4
18 6
10 8
5 20
7 5
20 7

实际上可以把问题看过一个数组的重新排列问题.用clusters[N]数组表示第i块cluster处放置的文件块的序号(块的序号按重排后结果编排,即该块最终应该位于哪一个cluster)。那么重排后的结果应该是前面部分的clusters[i]=i,后面的部分clusters[i]=0.

比如sample中的例子:

初始状态:

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

clusters[i]:  0  1  2  0  7  0  5  0  0   8    3    4    0    0   0    0    0    6

重排后:

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

clusters[i]:  1  2  3  4  5  5  6  8  0   0    0    0    0    0   0    0    0    0

遍历所有的cluster,会有以下几种情况:

1. clusters[i]=0,不必处理。

2. clusters[i]=1,不必处理。

3. 不是以上两种情况,则需要移动cluster。此时又有两种情况:

  a.需要移动的cluster形成链,例如:

     i:   1  2  3  4  5  6     

   clusters[i]: 5  0  4  2  3  0

   1被5占,5被3占,3被4占,4被2占,2为空。用栈保存占用关系,借助一个空位,逆向移动即可。

  b.需要移动的cluster形成环,例如:  

      i:  1  2  3  4  5  6     

    clusters: 5  1  4  2  3  0

  1被5占,5被3占,3被4占,4被2占,2又被1占。这种情况从磁盘末尾开始找一个空cluster(题目保证了一个至少有一个空的cluster,否则就移动不了了),借助这个空的cluster,然后逆向移动。

  遍历完成时磁盘整理也完成了。

 //////////////////////////////////////////////////////////////////////////
// POJ1033 Defragment
// Memory: 408K Time: 829MS
// Language: C++ Result: Accepted
////////////////////////////////////////////////////////////////////////// #include <iostream>
#include <stack> using namespace std; int main() {
int N;
int K;
int move_cnt = ;
cin >> N >> K; int * clusters = new int[N + ];
for (int i = ; i <= N; ++i) {
clusters[i] = ;
}
int sum = ;
for (int i = ; i < K; ++i) {
int n;
cin >> n;
for (int j = ; j <= n; ++j) {
int a;
cin >> a;
clusters[a] = ++sum;
}
}
for (int i = ; i <= N; ++i) {
if (clusters[i] == || clusters[i] == i) {
continue;
}
stack<int> s;
int next = clusters[i];
s.push(i);
bool isCircle = false;
while (true) {
if (clusters[next] == i) {
isCircle = true;
break;
} else if (clusters[next] == ) {
break;
}
s.push(next);
next = clusters[next];
}
if (isCircle == true) {
int j = N;
while (clusters[j] != ) {
--j;
continue;
}
cout << next << " " << j << endl;
clusters[j] = clusters[next];
int t;
while (!s.empty()) {
t = s.top();
cout << t << " " << next << endl;
clusters[next] = clusters[t];
next = t;
s.pop();
++move_cnt;
}
clusters[next] = clusters[j];
clusters[j] = ;
cout << j << " " << next << endl;
} else {
int t;
while (!s.empty()) {
t = s.top();
cout << t << " " << next << endl;
clusters[next] = clusters[t];
next = t;
s.pop();
++move_cnt;
}
clusters[next] = ;
}
}
if (move_cnt == ) {
cout << "No optimization needed" << endl;
}
system("pause");
return ;
}
05-11 22:12