转载于:https://www.cnblogs.com/damacheng/archive/2010/09/24/1833983.html
You are taking part in the development of a “New Generation” operating system and the NG file system. In this file system all disk space is divided into N clusters of the equal sizes, numbered by integers from 1 to N. Each file occupies one or more clusters in arbitrary areas of the disk. All clusters that are not occupied by files are considered to be free. A file can be read from the disk in the fastest way, if all its clusters are situated in the successive disk clusters in the natural order.
Rotation of the disk with constant speed implies that various amounts of time are needed for accessing its clusters. Therefore, reading of clusters located near the beginning of the disk performs faster than reading of the ones located near its ending. Thus, all files are numbered beforehand by integers from 1 to K in the order of descending frequency of access. Under the optimal placing of the files on the disk the file number 1 will occupy clusters 1, 2, …, S1, the file number 2 will occupy clusters S1+1, S1+2, …, S1+S2 and so on (here Si is the number of clusters which the i-th file occupies).
In order to place the files on the disk in the optimal way cluster-moving operations are executed. One cluster-moving operation includes reading of one occupied cluster from the disk to the memory and writing its contents to some free cluster. After that the first of them is declared free, and the second one is declared occupied.
Your goal is to place the files on the disk in the optimal way by executing the minimal possible number of cluster-moving operations.
The first line of the input file contains two integers N and K separated by a space(1 <= K < N <= 10000).Then K lines follow, each of them describes one file. The description of the i-th file starts with the integer Si that represents the number of clusters in the i-th file (1 <= Si < N). Then Si integers follow separated by spaces, which indicate the cluster numbers of this file on the disk in the natural order.
All cluster numbers in the input file are different and there is always at least one free cluster on the disk.
Your program should write to the output file any sequence of cluster-moving operations that are needed in order to place the files on the disk in the optimal way. Two integers Pj and Qj separated by a single space should represent each cluster-moving operation. Pj gives the cluster number that the data should be moved FROM and Qj gives the cluster number that this data should be moved TO.
The number of cluster-moving operations executed should be as small as possible. If the files on the disk are already placed in the optimal way the output should contain only the string “No optimization needed”.
20 3
4 2 3 11 12
1 7
3 18 5 10
2 1
3 2
11 3
12 4
18 6
10 8
5 20
7 5
20 7
点评:此题的通过率看起来挺吓人的,其实也不难。
题目大意:你要写一个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,则需要输出一行信息。
#include
#include
#include
#define MAX 10005
using std::stack;
int cluster[MAX]; // 簇的使用情况
int file_num,cluster_num; // 簇的总数和文件个数
int counter = 1 // 文件片段起始编号
int mov_num = 0; // 操作总数
stack<int> s;
void solve();
int main()
{
scanf("%d%d",&cluster_num,&file_num);
for(int i=0;i<file_num;i++)
{
int n,t;
scanf("%d",&n);
for(int j=0;j<n;j++)
{
scanf("%d",&t);
cluster[t] = counter++;
}
}
solve();
return 0;
}
void solve()
{
int next;
for(int i = 1;i<=cluster_num;i++)
{
if(cluster[i] == i)
continue;
else if(cluster[i] != 0)
{
s.push(i);
next = cluster[i];
bool is_circle = 0;
while(true)
{
if(cluster[next] == i)
{
is_circle = 1;
break;
}
else if(!cluster[next])
{
is_circle = 0;
break;
}
s.push(next);
next = cluster[next];
}
int j,t;
if(is_circle)
{
for(j = cluster_num;j>=0;j--)
if(!cluster[j])
break;
printf("%d %d\n",next,j);
cluster[j] = cluster[next];
while(!s.empty())
{
t = s.top();
printf("%d %d\n",t,next);
cluster[next] = cluster[t];
next = t;
mov_num++;
s.pop();
}
cluster[next] = cluster[j];
cluster[j] = 0;
printf("%d %d\n",j,next);
}
else
{
while(!s.empty())
{
t = s.top();
printf("%d %d\n",t,next);
cluster[next] = cluster[t];
next = t;
mov_num++;
s.pop();
}
cluster[next] = 0;
}
}
}
if(!mov_num)
puts("No optimization needed");
}
最近做的搜索的题目好难,题目描述花里胡哨,根本都看不懂题目。。。。。英语不过关的我流下的不学无术的泪水