b040. E. 魔法部的任務
內容 :
傳 說中,魔法部是個處理世界上各種魔法事件的神秘部門,他們的職責就是要保護魔法世界的隱密性,不要讓魔法干擾麻瓜們(魔法世界對不懂魔法的凡人的稱呼)的 生活。身為剛上任的魔法部長,你最近真是忙得焦頭爛額,因為「那個人」回來了(指的是黑魔王佛地魔,因為這個名字實在是太邪惡了,因此大家都以「那個人」 來稱呼他)!由於復活之後的「那個人」開始帶領食死人們在世界上到處作亂,讓你大傷腦筋。還好,你最近得到了一個魔法寶物──「預言之石」,它可以在當天 凌晨零時的時候預言出今天一天之內發生的魔法事件,於是你就可以即時安排正氣師去阻止食死人的行動。
由 於「那個人」不斷的在麻瓜世界裡作亂,因此正氣師得跑到麻瓜世界理去處理,所以就不能騎著掃把到處飛了(要不然被麻瓜們看到就糟糕了)。因此,他們只好學 著使用麻瓜世界的行動方式──開車。還好麻瓜世界的馬路是由一條條南北向的大道和東西向的街組成,就像棋盤一樣,因此每個路口都可以用兩個數字 (x, y) 表示,例如 (5, 3) 就代表第 5 大道第 3 街口。雖然不能騎掃把,正氣師還是可以用一點小小的魔法讓路上通行無阻,因此只要用一分鐘的時間就可以從一個路口到下一個路口,例如從 (5, 3) 開車到 (5, 4) 只要一分鐘就好了;而若是從 (5, 3) 開車到 (7, 5),則需要 (7-5) + (5-3) = 4 分鐘。
每 當一個魔法事件發生時,都得要有一位正氣師即時趕到才能處理(當然正氣師也可以提早到達發生地點,不過得等到事件發生才能處理)。如果這個正氣師是直接從 正氣師局動身的話,就可以用「現影術」瞬間移動到魔法事件發生的地點。而當正氣師處理完一件事的時候,如果趕得及,還可以再趕去處理另一個魔法事件,這時 就只能開車了(當然,他們隨時都有辦法弄來一部車)。但是最近的事情實在是太多了,讓正氣師局的人員都接應不暇,因此你得作最好的指派,使得可以出最少的 人力去處理完所有的魔法事件。
輸入說明
:
輸入資料的第一行有一個數字 n,表示你現在要處理 n 天的資料。每天的資料有許多行,第一行有個數字 m(1 ≤ m ≤ 1000),表示當天預言之石預告了 m 個魔法事件的發生。接下來有 m 行,每行有三個數字 t x y,表示在當天時間 t(0 ≤ t < 1440)的時候在第 x 大道第 y 街口(0 ≤ x, y ≤ 1000)會有魔法事件發生。你可以假設任兩個魔法事件不可能在同時同地發生。
輸出說明
:
輸出資料應該有 n 行,每行對應到輸入資料的每一天。每行有一個數字,表示當天最少要派出多少正氣師,才能處理完所有事件。
範例輸入 :
2 3 1 5 3 2 5 4 3 6 6 5 10 6 8 20 2 14 30 7 19 40 8 10 50 0 12
範例輸出 :
2 1
提示
:
出處
:
作法 : 將問題轉換成 DAG, 再用最少路徑覆蓋問題去解決它
此作法需要求最大匹配數
/**********************************************************************************/
/* Problem: b040 "E. 魔法部的任務" from 2005 NPSC 高中組初賽 */
/* Language: C (1170 Bytes) */
/* Result: AC(112ms, 4.2MB) judge by this@ZeroJudge */
/* Author: morris1028 at 2011-11-12 20:25:59 */
/**********************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct {
int x, y, v;
}Path;
Path D[1001];
int cmp(const void *i, const void *j) {
Path *a, *b;
a = (Path *)i, b = (Path *)j;
return a->v - b->v;
}
int map[1002][1002], Mt[1002];
char used[1002];
int mx[1002], my[1002];
int DFS(int now) {
int a, i;
for(a = 0; a < Mt[now]; a++) {
i = map[now][a];
if(!used[i]) {
used[i] = 1;
if(my[i] == 0 || DFS(my[i])) {
mx[now] = i, my[i] = now;
return 1;
}
}
}
return 0;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
int n, i, j;
scanf("%d", &n);
for(i = 0; i < n; i++) {
scanf("%d %d %d", &D[i].v, &D[i].x, &D[i].y);
}
memset(mx, 0, sizeof(mx));
memset(my, 0, sizeof(my));
memset(Mt, 0, sizeof(Mt));
qsort(D, n, sizeof(Path), cmp);
for(i = 0; i < n; i++)
for(j = i+1; j < n; j++)
if(abs(D[i].x-D[j].x)+abs(D[i].y-D[j].y) <= D[j].v-D[i].v)
map[i][Mt[i]++] = j;
int Ans = 0;
for(i = 0; i < n; i++)
if(!mx[i]) {
memset(used, 0, sizeof(used));
if(DFS(i))
Ans++;
}
printf("%d\n", n - Ans);
}
return 0;
}