1. 程式人生 > >演算法競賽入門經典(紫書)第四章——Spreadsheet Tracking UVA-512

演算法競賽入門經典(紫書)第四章——Spreadsheet Tracking UVA-512

題意:
模擬表格的操作:插入行、列,刪除行、列,交換格子
題目要求對給出的格子座標,輸出一系列操作後的格子座標或 GONE。

思路:
我們的思路是記錄下操作,然後對每一個座標進行一遍操作。

先來講記錄操作,我直接用 int 陣列記錄的,可以將操作進行編號,將編號記錄在每一行的 0 下標位置處,如 EX 為 1, DC 為 2, DR 為 3, IC 為 4, IR 為 5,int 陣列為 cmd[100010][20](題目中說了 A 不會超過 10,所以列數選 20 足夠),cmd[][0] 位置就用來記錄操作的編號。至於操作後的數字,可以直接記錄到 cmd[][0] 的後面。

然後講對每一個座標進行操作,
從題目中我們能夠看到如果原先的座標是 (x, y),
如果是插入行,在 x 前面(包括 x)插入了幾行 x 就要加上幾;
如果是插入列,在 y 前面(包括 y)插入了幾列 y 就要加上幾;
如果是刪除行,如果刪除的行裡有 x,則這個座標就 GONE 了,否則在 x 前面(不包括 x)刪除了幾行 x 就要減去幾;
如果是刪除列,如果刪除的列裡有 y,則這個座標就 GONE 了,否則在 y 前面(不包括 y)刪除了幾行 y 就要減去幾;
如果是交換格子,比如 (x1, y1) 和 (x2, y2) 互換,如果 (x1, y1) 就是 (x, y),那麼 (x, y) 的座標交換後就變成了 (x2, y2),如果 (x2, y2) 就是 (x, y),那麼 (x, y) 的座標交換後就變成了 (x1, y1)。
這裡我們只要按著上面的邏輯和我們儲存的操作格式去編寫程式碼就可以了。

下面對樣例進行解析:
按照 EX 為 1, DC 為 2, DR 為 3, IC 為 4, IR 為 5 記錄下操作後的陣列為

座標 (4, 8) 執行完第一個操作後變成 (3, 8),
執行完第二個操作後變成 (3, 5),
執行完第三個操作後變成 (3, 6),
執行完第四個操作後變成 (4, 6),
執行完第五個操作後變成 (4, 6),
所以結果是 Cell data in (4,8) moved to (4,6)

座標 (5, 5) 執行完第一個操作後就 GONE 了,
所以結果是 Cell data in (5,5) GONE

座標 (7, 8) 執行完第一個操作後變成 (5, 8),
執行完第二個操作後變成 (5, 5),
執行完第三個操作後變成 (5, 6),
執行完第四個操作後變成 (7, 6),
執行完第五個操作後變成 (7, 6),
所以結果是 Cell data in (7,8) moved to (7,6)

座標 (6, 5) 執行完第一個操作後變成 (4, 5),
執行完第二個操作後變成 (4, 4),
執行完第三個操作後變成 (4, 5),
執行完第四個操作後變成 (6, 5),
執行完第五個操作後變成 (1, 2),
所以結果是 Cell data in (6,5) moved to (1,2)

注意:
1. 輸出的時候字母別打錯了,,,我就在這 WA 了一次
2. 題目中有這樣一句話 For each insert and delete
command, the order of the rows or columns in the command has no signicance. 意思就是刪除和插入的時候,所以刪除或插入的行或列的序號順序沒有意義。即我們刪除和插入時要拿原始的座標和所刪除或插入行或列的號比較,而不是刪除一個行改變一次座標再去刪除下一行。在一次刪除或插入的操作裡,只能在最後出現一次對座標的加減。

程式碼:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<stack>
#include<queue>
#include<utility>
#include<vector>
#include<cmath>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
#include<sstream>
using namespace std;
typedef long long LL;


int r, c;
int n, m;
int cmd[100010][20];   //EX = 1, DC = 2, DR = 3, IC = 4, IR = 5

int main()
{
    freopen("in.txt", "r", stdin);
    int kase = 1;
    while(scanf("%d%d", &r, &c)==2 && r!=0 && c!=0){
        scanf("%d", &n);
        char ch[5];
        for(int i=0; i<n; i++){
            scanf("%s", ch);
            if(strcmp(ch, "EX") == 0){
                cmd[i][0] = 1;
                for(int j=1; j<=4; j++){
                    scanf("%d", &cmd[i][j]);
                }
            }else{
                if(strcmp(ch, "DC") == 0) cmd[i][0] = 2;
                else if(strcmp(ch, "DR") == 0) cmd[i][0] = 3;
                else if(strcmp(ch, "IC") == 0) cmd[i][0] = 4;
                else if(strcmp(ch, "IR") == 0) cmd[i][0] = 5;

                scanf("%d", &cmd[i][1]);
                for(int j=2; j<2+cmd[i][1]; j++){
                    scanf("%d", &cmd[i][j]);
                }
            }
        }

        if(kase != 1) printf("\n");
        printf("Spreadsheet #%d\n", kase++);

        scanf("%d", &m);
        int r1, c1;
        for(int i=0; i<m; i++){
            scanf("%d%d", &r1, &c1);
            printf("Cell data in (%d,%d) ", r1, c1);
            for(int j=0; j<n; j++){
                if(cmd[j][0] == 1){ //EX,交換
                    if(cmd[j][1]==r1 && cmd[j][2]==c1){
                        r1 = cmd[j][3]; c1 = cmd[j][4];
                    }else if(cmd[j][3]==r1 && cmd[j][4]==c1){
                        r1 = cmd[j][1]; c1 = cmd[j][2];
                    }
                }else if(cmd[j][0] == 2){  //DC,刪除列
                    int tmp = 0;
                    for(int k=2; k<2+cmd[j][1]; k++){
                        if(cmd[j][k] == c1){
                            c1 = -1; break;
                        }else if(cmd[j][k] < c1){
                            tmp++;
                        }
                    }
                    if(c1 != -1) c1 -= tmp;
                }else if(cmd[j][0] == 3){  //DR,刪除行
                    int tmp = 0;
                    for(int k=2; k<2+cmd[j][1]; k++){
                        if(cmd[j][k] == r1){
                            r1 = -1; break;
                        }else if(cmd[j][k] < r1){
                            tmp++;
                        }
                    }
                    if(r1 != -1) r1 -= tmp;
                }else if(cmd[j][0] == 4){  //IC,插入列
                    int tmp = 0;
                    for(int k=2; k<2+cmd[j][1]; k++){
                        if(cmd[j][k] <= c1){
                            tmp++;
                        }
                    }
                    c1 += tmp;
                }else if(cmd[j][0] == 5){  //IR,插入行
                    int tmp = 0;
                    for(int k=2; k<2+cmd[j][1]; k++){
                        if(cmd[j][k] <= r1){
                            tmp++;
                        }
                    }
                    r1 += tmp;
                }

                printf("%d, %d\n", r1, c1);
                if(r1<0 || c1<0) break;
            }

            if(r1<0 || c1<0){
                printf("GONE\n");
            }else{
                printf("moved to (%d,%d)\n", r1, c1);
            }
        }
    }
    return 0;
}