湘大OJ第1484题 Allocation of Memory

  湘大第1484题,Allocation of Memory题目链接)。

Allocation of Memory

Description

  科技发展的速度往往会超过最大胆的想象,盖茨先生很快就为自己的短视付出了代价。他开发的操作系统在内存管理上有重大局限,很快便不再适应个人计算机的飞速发展,所以他不得不请天才的你帮忙改写系统的内存管理模块。

  系统里可以有若干个进程在同时运行,假设系统的总内存大小为M字节,从前到后依次编号为1至M。一开始的时候所有的内存都是可用的。如果在某个时刻某个进程需要使用k字节的内存,它就会向操作系统发出申请,系统会从前到后寻找连续的一段k字节的可用内存,将其分配给该进程。如果同时有多段空间满足要求,会返回最靠前的一段。如果某进程终止,则它所申请的内存重新变为可用。

  可以发现,经过较长时间的运行之后,可能某个新的内存申请再也无法满足,而实际上系统里可能还有足够的可用空间,只是这些空间都成了碎片状。此时你的程序应该自动调用碎片整理过程,把所有当前被占用的空间都移动到内存空间的前部,并保持原来的顺序不变。这样在内存空间的后部可能就空余出了足够多的空间,然后系统继续调用之前的算法来分配内存。如果这样还没有足够的空间,则此次内存申请就失败了。

  你的程序应该对每次内存申请,输出一个地址,表示申请到的内存段的第一个字节的位置。如果申请失败,输出-1。

Input

  输入的第一行包含一个整数T (T ≤ 15),表示共有T组数据。接下来每组数据的第一行有两个数M, N(1 ≤ M, N ≤ 500),分别表示总内存容量和指令的数目。然后有N行,每行一条指令,指令有两种格式:
1) New process_id size 表示编号为process_id的进程申请了一块大小为size的内存
2) Quit process_id 表示编号为process_id的进程退出了,此处的process_id一定在以前出现过,但不保证其一定拥有内存空间

  在每组数据里任意两个进程的编号都不相同,编号为不超过10000的正整数,每次申请的内存大小为一个不超过M的正整数。一个进程可能多次申请内存,但是当进程退出后就不可能再申请内存了。

Output

  对每组数据,输出一行“Case X:”作为开头,此处X为从1开始的编号。注意首字母C为大写,在“Case”和编号X之间有一个空格,在编号X后面有一个冒号。然后对每个New指令输出一行,表示申请到的内存的第一个字节的位置。如果申请失败,输出-1。

Sample Input

2
10 7
New 1 3
New 2 2
New 1 2
New 3 2
Quit 1
New 4 5
New 4 5
5 5
New 1 5
New 2 5
Quit 1
New 3 5
Quit 2

Sample Output

Case 1:
1
4
6
8
5
-1
Case 2:
1
-1
1

Hint

对于第一组样例,在一号进程退出后内存空间的情况如下图所示:

         2 2       3 3   

此时找不到连续的5个空位,故开始碎片整理,整理结束以后的情况如下图:

2 2 3 3                  

则可以从第5个位置分配新的内存给4号进程:

2 2 3 3 4 4 4 4 4   

Source

“开启时代杯”湘潭市第二届大学生程序设计大赛 (Internet)

  解题思路直接暴力模拟。收到Quit信号,即清空内存为0。否则,察看如果有空间,若有,直接使用,赋值为pid,输出内存地址;否则,碎片整理,再看是否有空间,若有,直接使用,赋值为pid,输出内存地址;若无,输出-1。

  C语言源代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define MAX_MEMORY 510

typedef int COUNT;

int memory[MAX_MEMORY];
int maxMemory;

bool canAlloc( int start, int apply )
{
    COUNT i;
    for ( i = 0 ; i < apply ; i ++ )
    {
        if ( start + i > maxMemory )
            return false;
        if ( memory[start+i] != 0 )
            return false;
    }
    return true;
}

void defrag(void)
{
    COUNT i, j;
    for ( i = 1 ; i <= maxMemory ; i ++ )
    {
        if ( memory[i] == 0 )
        {
            for ( j = i + 1 ; j <= maxMemory ; j ++ )
            {
                if ( memory[j] != 0 )
                {
                    memory[i] = memory[j];
                    memory[j] = 0;
                    break;
                }
            }
        }
    }
}

int alloc( int pid, int apply )
{
    COUNT i, j;
    for ( i = 1 ; i <= maxMemory ; i ++ )
    {
        if ( memory[i] == 0 )
        {
            if ( canAlloc(i, apply) )
            {
                for ( j = 0 ; j < apply ; j ++ )
                    memory[i+j] = pid;
                return i;
            }
        }
    }
    defrag();
    for ( i = 1 ; i <= maxMemory ; i ++ )
    {
        if ( memory[i] == 0 )
        {
            if ( canAlloc(i, apply) )
            {
                for ( j = 0 ; j < apply ; j ++ )
                    memory[i+j] = pid;
                return i;
            }
        }
    }
    return -1;
}

void killprocess( int pid )
{
    COUNT i;
    for ( i = 1; i <= maxMemory ; i ++ )
    {
        if ( memory[i] == pid )
            memory[i] = 0;
    }
}

int main (void)
{
    int testcases;
    COUNT i, j;
    char cmd[12];
    int pid, apply;
    int instructions;
    scanf( "%d", &testcases );
    for ( i = 1 ; i <= testcases ; i ++ )
    {
        scanf( "%d%d", &maxMemory, &instructions );
        memset( memory, 0, sizeof(memory) );
        printf( "Case %d:\n", i );
        for ( j = 0 ; j < instructions ; j ++ )
        {
            scanf( "%s", cmd );
            if ( !strcmp( cmd, "New" ) )
            {
                scanf( "%d%d", &pid, &apply );
                printf( "%d\n", alloc( pid, apply ) );
            }
            else
            {
                scanf( "%d", &pid );
                killprocess( pid );
            }
        }
    }
    return EXIT_SUCCESS;
}
posted @ 2012-07-15 22:26  叶剑飞Victor  阅读(454)  评论(0编辑  收藏  举报