HDU 3533
/*
这题代码量太恶心了,中间还隔了一个星期写起来就和重写一样费劲
预处理处每个Castle的最远射程
然后存一个dp[i][j][k],表示(i,j)这个点在k时刻时能不能走到
判断Castle是否能射中某个人时那里比较啰嗦,不过没找到更好的写法
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100 + 5;
struct Castle
{
int per, vel;
int x, y;
int dx, dy;
int maxDis;
}ca[MAXN];
int caCnt;
int n, m;
int power;
char str[10];
struct Node
{
int x, y, d;
Node(){}
Node(int _x, int _y, int _d){x = _x, y = _y, d = _d;}
};
bool dp[MAXN][MAXN][MAXN * 10];
queue<Node>que;
int dirx[] = {-1, 0, 1, 0, 0};
int diry[] = {0, 1, 0, -1, 0};
bool validPos(int x, int y) {if(x >= 0 && x <= n && y >= 0 && y <= m) return true; else return false;}
bool validDis(int x, int tx, int midx)
{
if(abs(x - midx) < abs(tx - midx)) return true;
else return false;
}
int main()
{
// freopen("HDU 3533.in", "r", stdin);
while(scanf("%d%d%d%d", &n, &m, &caCnt, &power) != EOF) {
for(int i = 0 ; i < caCnt ; i++) {
scanf("%s%d%d%d%d", str, &ca[i].per, &ca[i].vel, &ca[i].x, &ca[i].y);
if(str[0] == 'N') ca[i].dx = -1, ca[i].dy = 0;
if(str[0] == 'S') ca[i].dx = 1, ca[i].dy = 0;
if(str[0] == 'W') ca[i].dx = 0, ca[i].dy = -1;
if(str[0] == 'E') ca[i].dx = 0, ca[i].dy = 1;
}
for(int i = 0 ; i < caCnt ; i++) {
int maxDis;
if(ca[i].dx < 0 || ca[i].dy < 0) maxDis = -1;
else if(ca[i].dx > 0) maxDis = n + 1;
else maxDis = m + 1;
for(int j = 0 ; j < caCnt ; j++) {
if(i == j) continue;
if(ca[i].dx && ca[i].y == ca[j].y) {
if(ca[i].x < ca[j].x && ca[i].dx > 0) maxDis = min(ca[j].x, maxDis);
else if(ca[i].x > ca[j].x && ca[i].dx < 0) maxDis = max(maxDis, ca[j].x);
}
else if(ca[i].dy && ca[i].x == ca[j].x) {
if(ca[i].y < ca[j].y && ca[i].dy > 0) maxDis = min(ca[j].y, maxDis);
else if(ca[i].y > ca[j].y && ca[i].dy < 0) maxDis = max(maxDis, ca[j].y);
}
}
ca[i].maxDis = maxDis;
}
// puts("///***Castle");
// for(int i = 0 ; i < caCnt ; i++){
// printf("dx = %d, dy = %d, per = %d, vel = %d", ca[i].dx, ca[i].dy, ca[i].per, ca[i].vel);
// printf("maxDis = %d\n", ca[i].maxDis);
// printf("x = %d, y = %d\n", ca[i].x, ca[i].y);
// }
// puts("***///Castle");
memset(dp, 0, sizeof dp);
dp[0][0][power] = 0;
while(!que.empty()) que.pop();
que.push(Node(0, 0, power));
int ans = -1;
while(!que.empty()) {
Node node = que.front(); que.pop();
for(int i = 0 ; i < 5 ; i++) {
int tx = node.x + dirx[i];
int ty = node.y + diry[i];
if(validPos(tx, ty) && dp[tx][ty][node.d - 1] == 0) {
int ok = 1;
for(int j = 0 ; j < caCnt ; j++) {
// if(j == 0) {
// printf("dx = %d, ca[j].y = %d, ty = %d\n");
// printf("ca[j].x - tx = %d, ca[j].dx = %d\n", ca[j].x - tx, ca[j].dx);
// printf("validDis = %d", validDis(tx, ca[j].maxDis, ca[j].x));
// }
if(tx == ca[j].x && ty == ca[j].y) ok = 0;
else if(ca[j].dx && ca[j].y == ty && (ca[j].x - tx) / ca[j].dx < 0 && validDis(tx, ca[j].maxDis, ca[j].x)) {
int Dis = abs(ca[j].x - tx);
if(Dis % ca[j].vel != 0) continue;
if(power - node.d + 1 - Dis / ca[j].vel < 0) continue;
if((power - node.d + 1 - Dis / ca[j].vel) % ca[j].per != 0) continue;
ok = 0;
}
else if(ca[j].dy && ca[j].x == tx && (ca[j].y - ty) / ca[j].dy < 0 && validDis(ty, ca[j].maxDis, ca[j].y)) {
int Dis = abs(ca[j].y - ty);
if(Dis % ca[j].vel != 0) continue;
if(power - node.d + 1 - Dis / ca[j].vel < 0) continue;
if((power - node.d + 1 - Dis / ca[j].vel) % ca[j].per != 0) continue;
ok = 0;
}
if(ok == 0) break;
}
// printf("node.x = %d, node.y = %d, node.d = %d\n", node.x, node.y, node.d);
// printf("tx = %d, ty = %d, ok = %d\n", tx, ty, ok);
// system("pause");
if(ok && dp[tx][ty][node.d - 1] == 0) {
if(node.d > 0)
que.push(Node(tx, ty, node.d - 1));
dp[tx][ty][node.d - 1] = 1;
if(tx == n && ty == m) {
ans = node.d - 1;
break;
}
}
}
}
if(ans != -1) break;
}
if(ans != -1 ) printf("%d\n", power - ans);
else puts("Bad luck!");
}
return 0;
}