語法書 / AA 競程語法書 上冊 / 第六單元 / 記憶體用量估計與 MLE

6.6 記憶體用量估計與 MLE

陣列會消耗記憶體。如果開的陣列太大,程式會因為記憶體不足被 OJ 判為 MLE(Memory Limit Exceed)。學會估算記憶體用量,是避免 MLE 的關鍵。

基本公式:

陣列記憶體用量 = 元素個數 × 單個元素的大小

常見資料型態的大小:

資料型態 位元數 位元組
bool 1 bit 1 B
char 8 bits 1 B
short 16 bits 2 B
int 32 bits 4 B
long long 64 bits 8 B
double 64 bits 8 B

單位換算:

1 KB = 2^10 Bytes ≈ 1000 B
1 MB = 2^20 Bytes ≈ 1,000,000 B
1 GB = 2^30 Bytes ≈ 1,000,000,000 B

範例程式碼

#include<iostream>
using namespace std;
int main() {
    // 假設題目記憶體限制是 256 MB
    const int MEMORY_LIMIT_MB = 256;
    const long long MEMORY_LIMIT_BYTES = MEMORY_LIMIT_MB * (1LL << 20);

    // 情境 1:開一個 int 陣列
    // int 佔 4 bytes,問能開多大?
    cout << "Max int elements: " << MEMORY_LIMIT_BYTES / 4 << '\n';

    // 情境 2:開一個 long long 陣列
    // long long 佔 8 bytes
    cout << "Max long long elements: " << MEMORY_LIMIT_BYTES / 8 << '\n';

    // 情境 3:開一個 2D 陣列 int[1000][1000]
    long long elements_2d = 1000LL * 1000 * sizeof(int);
    cout << "2D int[1000][1000] memory (MB): " << elements_2d / (1LL << 20) << '\n';

    return 0;
}

執行結果:

Max int elements: 67108864
Max long long elements: 33554432
2D int[1000][1000] memory (MB): 3

資源估計對照表

為了加強你對時間和記憶體的直覺,這裡列出常見的估計數據:

操作 時間複雜度 常用上限 備註
單個運算 O(1) N ≤ 10¹⁸ 加減乘除等
線性遍歷 O(N) N ≤ 10⁸ 一層迴圈
巢狀迴圈 O(N²) N ≤ 10⁴ 兩層迴圈
三層迴圈 O(N³) N ≤ 500 三層迴圈
資料結構 記憶體 常用上限 備註
int 陣列 4 B/元素 6.4 × 10⁷ 256 MB 限制
long long 陣列 8 B/元素 3.2 × 10⁷ 256 MB 限制
int[1000][1000] 4 MB ✓ 可行 普通地圖
int[10000][10000] 400 MB ✗ 超限 超過 256 MB

動手試試看:計算以下情境的記憶體用量:

  1. 一個 int a[10000000] 的陣列
  2. 一個 int grid[5000][5000] 的 2D 陣列
  3. 一個 long long cube[100][100][100] 的 3D 陣列

執行上面的程式碼,看看你的計算是否正確。