湘大第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; }