poj 1033

题目

Defragment
Time Limit: 2000MS   Memory Limit: 10000K
Total Submissions: 4450   Accepted: 1557
Case Time Limit: 1000MS   Special Judge

Description

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. 

Input

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. 

Output

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". 

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

代码

Source Code

Problem: 1033   User: PaladinDu
Memory: 224K   Time: 172MS
Language: C++   Result: Accepted
  • Source Code
    #include <stdio.h>
    /*
     * 磁盘整理,这个算是一个非常真实的需求了
     *
     * 有个比较简单的思路。
     * 一遍又一边的把可以直接填到对应位置的碎片填过去。
     * (此方案对于可以直接移动到所需地方的方法肯定是最短路径)
     * 当填到不能填的时候只可能是两种情况
     * 1.完成任务
     * 2.存在环 a -> b ,b -> c , c -> a
     *   环的长度不定但>1 环的个数不定。
     *   对于环的最快方式肯定是打破环,然后继续第一种方案
     *   然后再打破环,再继续第一种方案直到完成任务。
     *   环与环之间不会有影响
     * 剩下的就是优化了
     *
     *
     * 被注释的代码可以方便理解,但是并不会影响实际结果
    */
    #define __INT_MAX__ 10000
    
    int main () {
        short int DiskInfo[__INT_MAX__+1];//={0};
        short int DiskNeedFrag[__INT_MAX__+1];//disk 位置需要的块现在所在的位置
        short int LackDisk[__INT_MAX__+1];//缺失的需要填写的块,总是能直接填写正确的快
        short int i_lack_disk_len = 0;
        short int i_need_move = 0;
        short int N,K;
        short int i,j,k,id;
        short int frag_id = 0;
        scanf("%d %d",&N,&K);
        for(i=0;i<K;++i)
        {
            scanf("%d",&k);
            for(j=0;j<k;++j)
            {
                scanf("%d",&id);
                DiskInfo[id] = ++frag_id;
                DiskNeedFrag[frag_id]=id;//整理完成后的顺序是整齐的,所以碎片的id应该和整好之后的位置id相同
                if(id != frag_id) ++i_need_move;
            }
        }
        if (i_need_move==0)
        {
            printf("No optimization needed");
            return 0;
        }
        for(i=1;i<=frag_id;++i)//初始化空闲的位置,需要填写的
        {
            if(DiskInfo[i]==0)
            {
                LackDisk[++i_lack_disk_len]=i;
            }
        }
        i=1;
        while(i_need_move!=0)
        {
            //第一步:将非环的块填好
            while(i_lack_disk_len!=0)
            {
                id = LackDisk[i_lack_disk_len--];
                if(DiskNeedFrag[id]<=frag_id)
                {
                    LackDisk[++i_lack_disk_len] = DiskNeedFrag[id];
                }
                printf("%d %d\n",DiskNeedFrag[id],id);
                DiskInfo[id] = id;//移动一个碎片
    //            DiskInfo[DiskNeedFrag[id]] = 0;
    //            DiskNeedFrag[id] = id;//已经整好了
                --i_need_move;
            }
            if(i_need_move !=0)
            {//存在环,这里不用初始化i可以让寻找环的过程连续。这样就时间复杂度就是是n 而不是n2了
                for(;i<=frag_id;++i)
                {
                    if(DiskInfo[i] != i)
                    {
                        break;
                    }
                }
                //破坏环,此时 frag_id+1 到 N 肯定都是空的,随便找一个就好
                printf("%d %d\n",i,frag_id+1);
                DiskNeedFrag[DiskInfo[i]]=frag_id+1;
    //            DiskInfo[i]=0;
    //            DiskInfo[frag_id+1]=i;
                LackDisk[++i_lack_disk_len]=i;
            }
        }
        return 0;
    }

发布了54 篇原创文章 · 获赞 1 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/u011255131/article/details/54670114
今日推荐