# 北軟107 problemD ###### tags: `北軟107` ## 競賽題目: 簡易最適配置法之記憶體管理 (Memory Management---Best fit)程式 說明:在作業系統中,最適配置法之記憶體管理單元能依需求分配夠大而且最接 近需求的閒置空間來放置程序 (Process) 程式。 例如:有 3 個程序(如下左圖)所需佔用的記憶體空間分別為 5、6、8 個單位。 閒置的記憶體空間如下右圖,有 3 個區塊、大小分別為 7、5、9 個單位,一個記 憶體單位大小等同 2 個等號。 ![image alt](https://cdn.discordapp.com/attachments/592247718194184213/595850774425239573/unknown.png) 程序配置前的記憶體空間是空白的 (如上右圖上半部分),程序配置後的記憶體 空間是顯示程序號碼及數個等號 (如上右圖下半部分)。因採用最適配置法,P1 程序需要 5 個單位所以被配置到 >=5 單位的區塊 2,並用\=\=號填滿整區塊。P2 程 序需要 6 個單位所以被配置到 >=6 單位且最接近 6 個單位的區塊 1,並用\=\=號填 入該區塊,只留下 1 單位空間。P3 程序需要 8 個單位所以被配置到 >=8 單位且最 接近 8 個單位的區塊 3,並用\=\=號填入該區塊,只留下 1 單位空間。 目標: 1. 請寫一支程式如下圖所示,區塊數<6 和程序數<6,顯示相關訊息 (2 分)。 2. 可輸入記憶體區塊數量及程序數量(2分)。 3. 接著輸入每個記憶體區塊的大小,最後一個區塊輸入後才換行(4 分)。 4. 接著輸入每個程序所需的區塊大小,最後一個程序輸入後才換行(4 分)。 5. 接著採最適配置法依程序順序將相關資訊顯示出來(13 分)。 注意:不用處理資料輸入錯誤問題。 ![image alt](https://cdn.discordapp.com/attachments/592247718194184213/595851260062728213/unknown.png) 另一例子如下圖: 因採用最適配置法, P1 程序需要 8個單位所以被配置到 >=8 單位的區塊2,並用\=\=號填滿整區塊。 P2 程序需要 7 個單位,因沒有 >=7 單位的空間,所以未被配置。 P3 程序需要 6個單位所以被配置到 >=6 單位的區塊1,並用\=\=號填滿整區塊。 P4 程序需要 6 個單位,因沒有 >=6 單位的空間,所以未被配置。 ![image alt](https://cdn.discordapp.com/attachments/592247718194184213/595851657128968212/unknown.png) ## 解題想法 由於這題給的記憶體區塊數與程序數非常少,所以這題我們可以直接暴力破解。 開6個迴圈,每個迴圈從0開始,運行條件為變數數值小於記憶體區塊數,且變數數值遞增。 接下來,我們就能夠將變數數值當成該程序選擇哪個記憶體區塊,判斷是否放得進去。 由於我們要求最適配置,所以我們要盡可能的讓記憶體區塊的記憶體剩餘最少。 所以,在我們做上一個步驟時, 我們要設一個變數count來記錄剩餘的記憶體數量,且這個變數的初始值非常大。 再設一個陣列select來記錄第i個程序放置在哪個記憶體區塊。 和一個紀錄整數的List**陣列**group來紀錄在第i個記憶體區塊內有哪些程序。 在六個迴圈的內部程式碼,我們開一個vec來複製紀錄區塊數的陣列,和一個item來複製紀錄程序大小的陣列,和一個put來記錄該程序是否有放進去記憶體內。 接下來開一個迴圈來記錄記憶體的剩餘數量,假設剩餘數量小於count,就將count設為目前剩餘的數量,然後更新陣列select和group。 接下來設計界面(最麻煩的部分),這邊由於很直觀所以不多做講解。 ## 程式碼(C#) ```csharp= using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace problemD { class Program { static String fixedString(string str) { return str.PadRight(16, ' '); } static void printPart1(int n,int[] spaceArray) { Console.Write("     █"); for (int i = 0; i < n; i++) { for (int j = 0; j <= spaceArray[i]; j++) { Console.Write("█"); } } Console.WriteLine(); } static void printPart2(int n, int[] spaceArray) { Console.Write("     "); for (int i = 0; i < n; i++) { Console.Write("█"); Console.Write("".PadRight(spaceArray[i] * 2, ' ')); } Console.Write("█"); Console.WriteLine(); } static void printPart2(string str,int n, int[] spaceArray) { Console.Write(str); for (int i = 0; i < n; i++) { Console.Write("█"); Console.Write("".PadRight(spaceArray[i] * 2, ' ')); } Console.Write("█"); Console.WriteLine(); } static void printPart2(string str, int n, int[] spaceArray, int[] programming, List<int>[] group) { Console.Write(str); for (int i = 0; i < n; i++) { Console.Write("█"); string rst = ""; for (int j = 0; j < group[i].Count(); j++) { int id = group[i][j]; if (programming[id] == 0) continue; rst += ("P" + (id + 1)).PadRight(programming[id] * 2, '='); } rst = rst.PadRight(spaceArray[i]*2, ' '); Console.Write(rst); } Console.Write("█"); Console.WriteLine(); } static void printPart3(int n, int[] spaceArray) { Console.Write("      "); for (int i = 0; i < n; i++) { for (int j = 0; j < spaceArray[i]; j++) { Console.Write((j+1) + "-"); } Console.Write(" "); } Console.Write(" "); Console.WriteLine(); } static void Main(string[] args) { int n, m; Console.WriteLine("記憶體管理程式-最適配置法(Best Fit)"); Console.Write("請輸入記憶體區塊數(<6):"); n = Convert.ToInt32(Console.ReadLine()); Console.Write("請輸入程序數(<6):"); m = Convert.ToInt32(Console.ReadLine()); Console.WriteLine(); Console.WriteLine("請輸入各區塊大小(<10)---"); int[] spaceArray = new int[6]; int[] programArray = new int[6]; for (int i = 0; i < 6; spaceArray[i] = 0, i++) ; for (int i = 0; i < 6; programArray[i] = 0, i++) ; for(int i = 0; i < n; i++) { Console.Write("區塊" + (i + 1) + ":"); spaceArray[i] = Convert.ToInt16(Console.ReadKey().KeyChar - '0'); Console.Write(", "); } Console.WriteLine(); Console.WriteLine(); Console.WriteLine("請輸入各程式所需大小(<10)---"); for (int i = 0; i < m; i++) { Console.Write("程序" + (i + 1) + ":"); programArray[i] = Convert.ToInt16(Console.ReadKey().KeyChar - '0'); Console.Write(", "); } int[] select = new int[6]; List<int>[] group = new List<int>[6]; for (int i = 0; i < 6; select[i] = 0, i++); int count = 100000; for (int a = 0; a < n; a++) { for (int b = 0; b < n; b++) { for (int c = 0; c < n; c++) { for (int d = 0; d < n; d++) { for (int e = 0; e < n; e++) { for (int f = 0; f < n; f++) { int[] vec = new int[6]; int[] item = new int[6]; bool[] put = new bool[6]; for (int i = 0; i < 6; i++) { vec[i] = spaceArray[i]; } for (int i = 0; i < 6; i++) { item[i] = programArray[i]; } if (vec[a] - item[0] >= 0) { put[0] = true; vec[a] -= item[0]; } if (vec[b] - item[1] >= 0) { put[1] = true; vec[b] -= item[1]; } if (vec[c] - item[2] >= 0) { put[2] = true; vec[c] -= item[2]; } if (vec[d] - item[3] >= 0) { put[3] = true; vec[d] -= item[3]; } if (vec[e] - item[4] >= 0) { put[4] = true; vec[e] -= item[4]; } if (vec[f] - item[5] >= 0) { put[5] = true; vec[f] -= item[5]; } bool find = false; int mn = 0; for (int i = 0; i < 6 && find == false; i++) { mn += vec[i]; } if (mn < count) { select[0] = (put[0] == true ? a : -1); select[1] = (put[1] == true ? b : -1); select[2] = (put[2] == true ? c : -1); select[3] = (put[3] == true ? d : -1); select[4] = (put[4] == true ? e : -1); select[5] = (put[5] == true ? f : -1); for (int i = 0; i < 6; group[i] = new List<int>(), i++) ; for (int i = 0; i < select.Length; i++) { int val = select[i]; if (val == -1) continue; group[val].Add(i); } count = mn; } } } } } } } Console.WriteLine(); Console.WriteLine(); for (int i = 0; i <= m; i++) { if(i == 0) { Console.WriteLine("程式編號    所需大小    區塊編號    區塊大小    剩餘空間"); continue; } Console.Write(fixedString(i.ToString())); Console.Write(fixedString(programArray[i - 1].ToString())); int sel = select[i - 1]; if (sel != -1) { Console.Write(fixedString((select[i - 1] + 1).ToString())); Console.Write(fixedString(spaceArray[select[i - 1]].ToString())); Console.Write(fixedString((spaceArray[select[i - 1]] - programArray[i - 1]).ToString())); } else { Console.Write("未分配記憶體區塊"); Console.Write(fixedString("")); Console.Write(fixedString("")); } Console.WriteLine(); } Console.WriteLine(); printPart1(n, spaceArray); printPart2(n, spaceArray); printPart2("配置程序前", n, spaceArray); printPart2(n, spaceArray); printPart1(n, spaceArray); printPart3(n, spaceArray); printPart1(n, spaceArray); printPart2(n, spaceArray); printPart2("程序配置後", n, spaceArray,programArray,group); printPart2(n, spaceArray); printPart1(n, spaceArray); } } } ```