HDU 3533

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值