置頂

我的 VPython 教學文件 (HackMD 版本)

VPython 教學文件目錄 安裝及測試 基本語法 等速度直線運動 自由落下 終端速度 水平抛射 使用For迴圈計算水平抛射資料 斜向抛射 圓周運動 簡諧運動 單擺 木塊彈簧系統分離 重力及簡諧 行星運動 相疊木塊 雙重簡諧運動 一維彈性碰撞 ...

熱門文章

2026年10月19日 星期一

ZeroJudge 解題筆記:f435.10267-Graphical Editor

作者:王一哲
日期:2026年10月19日


ZeroJudge 題目連結:f435.10267-Graphical Editor

解題想法


這題要模擬圖片編輯的操作過程,共有 8 個操作指令,雖然每個部分都不難,但是寫起來很長。指令開頭皆為一個大寫英文字母,後面再接上整數或字母。指令及功能分別為
  1. I M N:創造 $M \times N$ 的表格且每個像素的顏色為大寫英文字母 O。需要特別注意,題目的軸方向不一樣,這裡指的是表格有 N 列、M 欄。可以用二維陣列或是 C++ vector 搭配 string 儲存表格。
  2. C:使目前的表格顏色全為大寫英文字母 O,可以用迴圈或是 C++ vector.assign 處理。
  3. L X Y C:使 $(X,Y)$ 的像素顏色為 C。需要特別注意,題目的軸方向不一樣,而且是從 1 開始計算位置,這裡指的是二維陣列索引值 $[Y - 1][X - 1]$ 的格子。
  4. V X Y1 Y2 C:使 $(X, Y1) \dots (X, Y2)$ 的顏色為 C。需要特別注意,題目的軸方向不一樣,而且是從 1 開始計算位置,這裡指的是二維陣列索引值 $[Y1 - 1][X]$ 到 $[Y2 - 1][X]$ 的格子。
  5. H X1 X2 Y C:使 $(X1, Y) \dots (X2, Y)$ 的顏色為 C。需要特別注意,題目的軸方向不一樣,而且是從 1 開始計算位置,這裡指的是二維陣列索引值 $[Y][X1 - 1]$ 到 $[Y][X2 - 1]$ 的格子。
  6. K X1 Y1 X2 Y2 C:使由 $(X1, Y1)$ 為左上角、$(X2, Y2)$ 為右下角組成的矩形中所有的像素顏色為 C,可以用二層 for 迴圈處理。需要特別注意,題目的軸方向不一樣,而且是從 1 開始計算位置,這裡指的是二維陣列索引值 $[Y1 - 1][X1 - 1]$ 到 $[Y2 - 1][X2 - 1]$ 的格子。
  7. F X Y C:使 $(X, Y)$ 附近與它同顏色的像素顏色為 C,可以用 BFS 處理。需要特別注意,如果這格的顏色與 C 相同,不需要處理。題目的軸方向不一樣,而且是從 1 開始計算位置,這裡指的是二維陣列索引值 $[Y - 1][X - 1]$ 的格子。
  8. S Name:輸出 Name 之後輸出目前的表格。
  9. X:停止操作


Python 程式碼


使用時間約為 0.2 s,記憶體約為 11.4 MB,通過測試。
def solve():
    import sys
    from collections import deque

    result = []
    data = sys.stdin.read().split()
    ptr = 0
    
    graph = []  # 圖片
    m, n = 0, 0  # 圖片尺寸 n 列 m 欄
    
    while ptr < len(data):
        op = data[ptr]
        ptr += 1
        if op == "I":  # 建立 n 列 m 欄的圖片,內容皆為 O
            m = int(data[ptr])
            n = int(data[ptr + 1])
            ptr += 2
            graph = [["O"] * m for _ in range(n)]
        elif op == "C":  # 重置 n 列 m 欄的圖片,內容皆為 O
            graph = [["O"] * m for _ in range(n)]
        elif op == "L":  # 改變 graph[y][x] 為指定的顏色
            x = int(data[ptr]) - 1
            y = int(data[ptr + 1]) - 1
            ch = data[ptr + 2]
            ptr += 3
            graph[y][x] = ch
        elif op == "V":  # 改變 graph[y1][x] ~ graph[y2][x] 為指定的顏色
            x = int(data[ptr]) - 1
            y1 = int(data[ptr + 1]) - 1
            y2 = int(data[ptr + 2]) - 1
            ch = data[ptr + 3]
            ptr += 4
            for r in range(y1, y2 + 1):
                graph[r][x] = ch
        elif op == "H":  # 改變 graph[y][x1] ~ graph[y][x2] 為指定的顏色
            x1 = int(data[ptr]) - 1 
            x2 = int(data[ptr + 1]) - 1
            y = int(data[ptr + 2]) - 1
            ch = data[ptr + 3]
            ptr += 4
            graph[y][x1 : x2 + 1] = [ch] * (x2 - x1 + 1)
        elif op == "K":  # 改變 graph[y1][x1] ~ graph[y2][x2] 的矩形區域為指定的顏色
            x1 = int(data[ptr]) - 1
            y1 = int(data[ptr + 1]) - 1
            x2 = int(data[ptr + 2]) - 1
            y2 = int(data[ptr + 3]) - 1
            ch = data[ptr + 4]
            ptr += 5
            for r in range(y1, y2 + 1):
                for c in range(x1, x2 + 1):
                    graph[r][c] = ch
        elif op == "F":  # 將 graph[y][x] 及相鄰同色的格子改為指定的顏色
            x = int(data[ptr]) - 1
            y = int(data[ptr + 1]) - 1 
            ch = data[ptr + 2]
            ptr += 3
            target = graph[y][x]  # 目標顏色
            if target == ch: continue  # 目標顏色與新的顏色相同,不需要改變
            graph[y][x] = ch
            que = deque([(y, x)])
            while que:  # BFS
                r, c = que.popleft()
                for dr, dc in ((0, 1), (1, 0), (0, -1), (-1, 0)):
                    nr, nc = r + dr, c + dc
                    if 0 <= nr < n and 0 <= nc < m and graph[nr][nc] == target:
                        graph[nr][nc] = ch
                        que.append((nr, nc))
        elif op == "S":  # 儲存圖片,印出檔名及目前的圖片
            name = data[ptr]
            result.append(f"{name}\n")
            for row in graph:
                res = "".join(map(str, row)) + "\n"
                result.append(res)
        elif op == "X":  # 結束操作
            continue
    # 輸出答案
    sys.stdout.write("".join(result))

if __name__ == "__main__":
    solve()


先開好 graph 為題目預設的最大尺寸 $250 \times 250$,之後只重設指定的範圍。使用時間約為 0.2 s,記憶體約為 11.2 MB,通過測試。

def solve():
    import sys
    from collections import deque

    result = []
    data = sys.stdin.read().split()
    ptr = 0
    
    graph = [["O"] * 250 for _ in range(250)]  # 圖片,直接開好預設的最大尺寸 250*250
    m, n = 0, 0  # 圖片尺寸 n 列 m 欄
    
    while ptr < len(data):
        op = data[ptr]
        ptr += 1
        if op == "I":  # 建立 n 列 m 欄的圖片,內容皆為 O
            m = int(data[ptr])
            n = int(data[ptr + 1])
            ptr += 2
            for r in range(n):
                graph[r][:m] = ["O"] * m
        elif op == "C":  # 重置 n 列 m 欄的圖片,內容皆為 O
            for r in range(n):
                graph[r][:m] = ["O"] * m
        elif op == "L":  # 改變 graph[y][x] 為指定的顏色
            x = int(data[ptr]) - 1
            y = int(data[ptr + 1]) - 1
            ch = data[ptr + 2]
            ptr += 3
            graph[y][x] = ch
        elif op == "V":  # 改變 graph[y1][x] ~ graph[y2][x] 為指定的顏色
            x = int(data[ptr]) - 1
            y1 = int(data[ptr + 1]) - 1
            y2 = int(data[ptr + 2]) - 1
            ch = data[ptr + 3]
            ptr += 4
            for r in range(y1, y2 + 1):
                graph[r][x] = ch
        elif op == "H":  # 改變 graph[y][x1] ~ graph[y][x2] 為指定的顏色
            x1 = int(data[ptr]) - 1 
            x2 = int(data[ptr + 1]) - 1
            y = int(data[ptr + 2]) - 1
            ch = data[ptr + 3]
            ptr += 4
            graph[y][x1 : x2 + 1] = [ch] * (x2 - x1 + 1)
        elif op == "K":  # 改變 graph[y1][x1] ~ graph[y2][x2] 的矩形區域為指定的顏色
            x1 = int(data[ptr]) - 1
            y1 = int(data[ptr + 1]) - 1
            x2 = int(data[ptr + 2]) - 1
            y2 = int(data[ptr + 3]) - 1
            ch = data[ptr + 4]
            ptr += 5
            for r in range(y1, y2 + 1):
                for c in range(x1, x2 + 1):
                    graph[r][c] = ch
        elif op == "F":  # 將 graph[y][x] 及相鄰同色的格子改為指定的顏色
            x = int(data[ptr]) - 1
            y = int(data[ptr + 1]) - 1 
            ch = data[ptr + 2]
            ptr += 3
            target = graph[y][x]  # 目標顏色
            if target == ch: continue  # 目標顏色與新的顏色相同,不需要改變
            graph[y][x] = ch
            que = deque([(y, x)])
            while que:  # BFS
                r, c = que.popleft()
                for dr, dc in ((0, 1), (1, 0), (0, -1), (-1, 0)):
                    nr, nc = r + dr, c + dc
                    if 0 <= nr < n and 0 <= nc < m and graph[nr][nc] == target:
                        graph[nr][nc] = ch
                        que.append((nr, nc))
        elif op == "S":  # 儲存圖片,印出檔名及目前的圖片
            name = data[ptr]
            result.append(f"{name}\n")
            for row in graph[:n]:  # 只印出 graph[0][0] ~ graph[n-1][m-1]
                res = "".join(map(str, row[:m])) + "\n"
                result.append(res)
        elif op == "X":  # 結束操作
            continue
    # 輸出答案
    sys.stdout.write("".join(result))

if __name__ == "__main__":
    solve()


C++ 程式碼


使用時間約為 5 ms,記憶體約為 3.6 MB,通過測試。
#include <iostream>
#include <vector>
#include <queue>
#include <utility>
using namespace std;

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    
    vector<string> graph;  // 圖片
    int m = 0, n = 0;  // 圖片尺寸 n 列 m 欄
    string op;

    while(cin >> op) {
        if (op == "I") {  // 建立 n 列 m 欄的圖片,內容皆為 O
            cin >> m >> n;
            string row (m, 'O');
            graph.assign(n, row);
        } else if (op == "C") {  // 重置 n 列 m 欄的圖片,內容皆為 O
            string row (m, 'O');
            graph.assign(n, row);
        } else if (op == "L") {  // 改變 graph[y][x] 為指定的顏色
            int x, y;
            char ch;
            cin >> x >> y >> ch;
            graph[y - 1][x - 1] = ch;
        } else if (op == "V") {  // 改變 graph[y1][x] ~ graph[y2][x] 為指定的顏色
            int x, y1, y2;
            char ch;
            cin >> x >> y1 >> y2 >> ch;
            x--; y1--; y2--;
            for(int r = y1; r <= y2; r++) {
                graph[r][x] = ch;
            }
        } else if (op == "H") {  // 改變 graph[y][x1] ~ graph[y][x2] 為指定的顏色
            int x1, x2, y;
            char ch;
            cin >> x1 >> x2 >> y >> ch;
            x1--; x2--; y--;
            for(int c = x1; c <= x2; c++) {
                graph[y][c] = ch;
            }
        } else if (op == "K") {  // 改變 graph[y1][x1] ~ graph[y2][x2] 的矩形區域為指定的顏色
            int x1, x2, y1, y2;
            char ch;
            cin >> x1 >> y1 >> x2 >> y2 >> ch;
            x1--; y1--; x2--; y2--;
            for(int r = y1; r <= y2; r++) {
                for(int c = x1; c <= x2; c++) {
                    graph[r][c] = ch;
                }
            }
        } else if (op == "F") {  // 將 graph[y][x] 及相鄰同色的格子改為指定的顏色
            int x, y;
            char ch;
            cin >> x >> y >> ch;
            x--; y--;
            char target = graph[y][x];  // 目標顏色
            if (target == ch) continue;  // 目標顏色與新的顏色相同,不需要改變
            graph[y][x] = ch;
            queue<pair<int, int>> que;
            que.push({y, x});
            int dr[4] = {0, 1, 0, -1}, dc[4] = {1, 0, -1, 0};
            while(!que.empty()) {  // BFS
                int r = que.front().first, c = que.front().second;
                que.pop();
                for(int i = 0; i < 4; i++) {
                    int nr = r + dr[i], nc = c + dc[i];
                    if (nr >= 0 && nr < n && nc >= 0 && nc < m && graph[nr][nc] == target) {
                        graph[nr][nc] = ch;
                        que.push({nr, nc});
                    }
                }
            }
        } else if (op == "S") {  // 儲存圖片,印出檔名及目前的圖片
            string name;
            cin >> name;
            cout << name << "\n";
            for(auto row : graph) {
                cout << row << "\n";
            }
        } else if (op == "X") {  // 結束操作
            continue;
        }
    }
    return 0;
}


C 語言程式碼


使用時間約為 5 ms,記憶體約為 2.2 MB,通過測試。
#include <stdio.h>

typedef struct {
    int r, c;
} Pos;

int main() {
    char graph[250][250];  // 圖片,題目上限 250 * 250
    int m = 0, n = 0;  // 圖片尺寸 n 列 m 欄
    char op;

    while(scanf(" %c", &op) != EOF) {
        if (op == 'I') {  // 建立 n 列 m 欄的圖片,內容皆為 O
            scanf("%d %d", &m, &n);
            for(int r = 0; r < n; r++) {
                for(int c = 0; c < m; c++) {
                    graph[r][c] = 'O';
                }
            }
        } else if (op == 'C') {  // 重置 n 列 m 欄的圖片,內容皆為 O
            for(int r = 0; r < n; r++) {
                for(int c = 0; c < m; c++) {
                    graph[r][c] = 'O';
                }
            }
        } else if (op == 'L') {  // 改變 graph[y][x] 為指定的顏色
            int x, y;
            char ch;
            scanf("%d %d %c", &x, &y, &ch);
            graph[y - 1][x - 1] = ch;
        } else if (op == 'V') {  // 改變 graph[y1][x] ~ graph[y2][x] 為指定的顏色
            int x, y1, y2;
            char ch;
            scanf("%d %d %d %c", &x, &y1, &y2, &ch);
            x--; y1--; y2--;
            for(int r = y1; r <= y2; r++) {
                graph[r][x] = ch;
            }
        } else if (op == 'H') {  // 改變 graph[y][x1] ~ graph[y][x2] 為指定的顏色
            int x1, x2, y;
            char ch;
            scanf("%d %d %d %c", &x1, &x2, &y, &ch);
            x1--; x2--; y--;
            for(int c = x1; c <= x2; c++) {
                graph[y][c] = ch;
            }
        } else if (op == 'K') {  // 改變 graph[y1][x1] ~ graph[y2][x2] 的矩形區域為指定的顏色
            int x1, x2, y1, y2;
            char ch;
            scanf("%d %d %d %d %c", &x1, &y1, &x2, &y2, &ch);
            x1--; y1--; x2--; y2--;
            for(int r = y1; r <= y2; r++) {
                for(int c = x1; c <= x2; c++) {
                    graph[r][c] = ch;
                }
            }
        } else if (op == 'F') {  // 將 graph[y][x] 及相鄰同色的格子改為指定的顏色
            int x, y;
            char ch;
            scanf("%d %d %c", &x, &y, &ch);
            x--; y--;
            char target = graph[y][x];  // 目標顏色
            if (target == ch) continue;  // 目標顏色與新的顏色相同,不需要改變
            graph[y][x] = ch;
            Pos que[90000];  // 最多走 250 * 250 = 87500 格
            que[0].c = x; que[0].r = y;
            int head = 0, total = 1;  // 讀取 que 的索引值,que 的總長
            int dr[4] = {0, 1, 0, -1}, dc[4] = {1, 0, -1, 0};  // 位移量
            while(head < total) {  // BFS
                int r = que[head].r, c = que[head].c;
                head++;
                for(int i = 0; i < 4; i++) {
                    int nr = r + dr[i], nc = c + dc[i];
                    if (nr >= 0 && nr < n && nc >= 0 && nc < m && graph[nr][nc] == target) {
                        graph[nr][nc] = ch;
                        que[total].r = nr;
                        que[total].c = nc;
                        total++;
                    }
                }
            }
        } else if (op == 'S') {  // 儲存圖片,印出檔名及目前的圖片
            char name[250];
            scanf(" %s", name);
            printf("%s\n", name);
            for(int r = 0; r < n; r++) {
                for(int c = 0; c < m; c++) {
                    printf("%c", graph[r][c]);
                }
                printf("\n");
            }
        } else if (op == 'X') {  // 結束操作
            continue;
        }
    }
    return 0;
}


沒有留言:

張貼留言