2011-06-14 22:18:08Morris

d933. E. 傘兵

http://zerojudge.tw/ShowProblem?problemid=d933

內容 :

  「報告將軍,有緊急狀況。」

  「說!」

  「前線遭遇伏擊,兄弟們死傷慘重,請求補給與增援。」

  「嗯

  「將軍!我們不能白白讓他們送死啊!」

  

  「將軍!」

  「好吧,派出傘兵中隊空降支援前線!」

  你的任務來了:
你手上有前線區域的地圖,地圖劃分為 R × C 的小格子。我們用 (r, c) 代表由北向南數來第 r 排,由西向東數來第 c 個小格子。你不知道前線部隊確切的位置,因為那是最高機密,不過你確定他們一定在地圖上的某處。然而,由於地形、天候、敵人視線等等因素,不是地圖上的每個地方都可以空降傘兵。可以空降的地方共有 N 個,座標分別是 (r1, c1), (r2, c2), · · · , (rN, cN)

  空降在每個的地方都有一些風險,用: v1, v2, · · · , vN 表示,值越大代表風險越高。空降下去的傘兵會知道前線部隊的確切位置,並且會往那個位置移動。傘兵可以從一個小格子移動到上下左右相鄰的小格子,而且每移動一格都會增加 1 單位的風險。這整個支援任務的總風險就是空降的風險加上傘兵移動的風險

  請你利用地圖和可以空降的地方的資料,算出派傘兵到地圖上每個地方的最小總風險。

輸入說明 :

第一行有一個整數 T ,代表接下來有幾組測試資料。兩筆測試資料中問會以一個空行隔開。

  每一筆的第一行有 R C N 三個整數,意思如題目所述。接下來有 N 行,每行有三個整數 ri ci vi,代表第 i 個可以空降的地方的座標和風險。

  • 1 ≤ R,C 100

  • 1 N 1000

  • 1 ri R, 1 cC, 0 v10000

  • i j (ri , ci) (rj , cj)

輸出說明 :

請對每筆測試資料輸出 R 行,每行有 C 個數字,第 r 行第 c 個數字代表派傘兵到 (r, c) 支援的最小總風險。兩個數字間請用一個空白隔開,兩筆測試資料間也請用一個空行隔開。

範例輸入 :

2
3 3 1
2 2 5
2 2 2
1 1 9
2 1 4

範例輸出 :

7 6 7
6 5 6
7 6 7
5 6
4 5

提示 :

出處 :

2010 NPSC 國中組初賽 (管理:pcshic)



作法 : BFS
water fill
怕效率太差,將空降地點的風險由小排到大,適時地納入queue中

否則 對每一個點都做一次water fill 最慘是O(R*C*N)

/**********************************************************************************/
/*  Problem: d933 "E. 傘兵" from 2010 NPSC 國中組初賽                      */
/*  Language: C                                                                   */
/*  Result: AC (24ms, 448KB) on ZeroJudge                                         */
/*  Author: morris1028 at 2011-06-12 20:31:43                                     */
/**********************************************************************************/


#include<stdio.h>
struct Queue {
    int x, y;
}Q[10001];
struct coordinate{
    int t, x, y;
}set[1001], X[1001];
void Merge(int l, int m, int h) {
    int In1 = l, In2 = m+1;
    int a, b, Top=0;
    while(In1 <= m && In2 <= h)
        if(set[In1].t < set[In2].t)
             X[Top++] = set[In1++];
       else  X[Top++] = set[In2++];
    while(In1 <= m)   X[Top++] = set[In1++];
    while(In2 <= h)   X[Top++] = set[In2++];
    for(a = 0, b = l; a < Top; a++, b++)
        set[b] = X[a];
}
void MergeSort(int l, int h) {
    if(l < h) {
        int m = (l+h)/2;
        MergeSort(l  , m);
        MergeSort(m+1, h);
        Merge(l, m, h);
    }
}
main() {
    int T, R, C, N, r, c, v, a, b;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d %d", &R, &C, &N);
        int Map[101][101];
        
        for(a = 0; a < N; a++) {
            scanf("%d %d %d", &r, &c, &v);
            Map[r][c] = v;
            set[a].t = v, set[a].x = r, set[a].y = c;
        }
        MergeSort(0, N-1);
       
        int Qt = 0, Used[101][101] = {}, tx, ty, ins = 1;
        Q[0].x = set[0].x, Q[0].y = set[0].y, Used[Q[0].x][Q[0].y] = 1;
        for(a = 0; a <= Qt; a++) {
            tx = Q[a].x, ty = Q[a].y;
            while(ins < N && Map[tx][ty] == set[ins].t) {
                Q[++Qt].x = set[ins].x, Q[Qt].y = set[ins++].y;
                Used[Q[Qt].x][Q[Qt].y] = 1;
            }
           
            if(tx+1<= R && Used[tx+1][ty] == 0) {
                Used[tx+1][ty] = 1;
                Map[tx+1][ty] = Map[tx][ty]+1;
                Q[++Qt].x = tx+1, Q[Qt].y = ty;
            }
            if(ty+1<= C && Used[tx][ty+1] == 0) {
                Used[tx][ty+1] = 1;
                Map[tx][ty+1] = Map[tx][ty]+1;
                Q[++Qt].x = tx, Q[Qt].y = ty+1;
            }
            if(tx-1>=1 && Used[tx-1][ty] == 0) {
                Used[tx-1][ty] = 1;
                Map[tx-1][ty] = Map[tx][ty]+1;
                Q[++Qt].x = tx-1, Q[Qt].y = ty;
            }
            if(ty-1>=1 && Used[tx][ty-1] == 0) {
                Used[tx][ty-1] = 1;
                Map[tx][ty-1] = Map[tx][ty]+1;
                Q[++Qt].x = tx, Q[Qt].y = ty-1;
            }
        }
        for(a = 1; a <= R; puts(""), a++)
            for(b = 1; b <= C; b++)
                printf("%d ", Map[a][b]);
    }
    return 0;
}