HDU4784 Dinner Coming Soon BFS

题目链接

题目大意

有一个地图,地图上面有n个点,m条有向的路,然后经过一条路要花费一定的时间,同时还得花一定的过路费。有一个人,最初在1点,他出门的时候会带上一些钱。每经过一个点,就可以买一包盐或者卖一包盐,赚取差价,或者什么也不干。他出门带了R的钱,没有带盐。他最多能带B的钱。现在要求他在T时间内到达N点。同时又有K个平行世界,起初这个人在第0个平行世界,这个人可以在平行世界之间穿越。比如他在第i个平行世界,他可以花费1分钟穿越到第(i+1)%K个平行世界,但是在1点和N点不能穿越。现在问的就是这个人及时到达N点且在第0个平行世界的时候,能得到的最多的钱。

解题思路

参考博客:http://blog.csdn.net/qian99/article/details/16371385

(这道题真的还不是我想出来的,看了题解才有的结果)
首先,其实点不多,平行世界不多,边不多,同时B也不大,就容易想到最短路,现在有两种想法,spfa或者广搜。
听说spfa姿势不好容易被卡常数,而且HDU更加容易被卡,那么就用广搜+优先级队列吧……首先,我们要保证时间最短,因为我们的第一个保证是能够及时到达N点,然后在此基础上保证钱最多。但是这道题还要复杂些,因为有K个平行世界。那么在一个点上,就能衍生出两个大状态:往前走或者穿越。然后往前走和穿越又各有三个小状态:买一包盐,卖一包盐或者什么都不干。能扩展出来的状态有这么多,每一个状态的限制条件题里面已经给出了,剩下的事情就交给程序了……

CODE

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 100+10;
const int maxm = 200+10;
struct edge{
    int v, tm, cost, next;
};
edge e[maxn<<1];
int head[maxn], tot = 0;
int n, m, K, B, R, T;
int d[maxn][maxm][6][6];
bool inq[maxn][maxm][6][6];
int prices[6][maxn];
void addedge(int u, int v, int tm, int cost){
    e[tot].v = v; e[tot].tm = tm; e[tot].cost = cost;
    e[tot].next = head[u]; head[u] = tot++;
}
struct Node{
    int u, times, k, b;
    Node(){}
    Node(int a, int x, int c, int d) : u(a), times(x), k(c), b(d){}
    bool operator < (const Node &rhs)const{
        return times > rhs.times;
    }
};
int bfs(){
    memset(d, 0xff, sizeof(d));
    memset(inq, 0, sizeof(inq));
    d[1][0][0][0] = R;
    Node node, tmp;
    priority_queue<Node> que;
    node = Node(1, 0, 0, 0);
    inq[1][0][0][0] = 1; que.push(node);
    bool flag = 0;
    while(!que.empty()){
        node = que.top(); que.pop();
        if (node.times > T) break;
        int u = node.u;
        if (u == n) continue;
        for (int i = head[u]; i != -1; i = e[i].next){
            int v = e[i].v;
            int cost, tim;
            cost = d[u][node.times][node.k][node.b]-e[i].cost;
            tim = node.times+e[i].tm;
            if (tim > T || cost < 0) continue;
            if (v == n && node.k != 0) continue;
            if (v == n) flag = 1;
            tmp.u = v; tmp.times = tim; tmp.k = node.k;
            if (u != 1 && u != n){
                if (node.b+1 <= B && cost-prices[node.k][u] > d[v][tim][node.k][node.b+1]){
                    d[v][tim][node.k][node.b+1] = cost-prices[node.k][u];
                    tmp.b = node.b+1;
                    if (!inq[tmp.u][tmp.times][tmp.k][tmp.b]){
                        inq[tmp.u][tmp.times][tmp.k][tmp.b] = 1;
                        que.push(tmp);
                    }
                }
                if (node.b > 0 && cost+prices[node.k][u] > d[v][tim][node.k][node.b-1]){
                    d[v][tim][node.k][node.b-1] = cost+prices[node.k][u];
                    tmp.b = node.b-1;
                    if (!inq[tmp.u][tmp.times][tmp.k][tmp.b]){
                        inq[tmp.u][tmp.times][tmp.k][tmp.b] = 1;
                        que.push(tmp);
                    }
                }
            }
            if (cost > d[v][tim][node.k][node.b]){
                d[v][tim][node.k][node.b] = cost;
                tmp.b = node.b;
                if (!inq[tmp.u][tmp.times][tmp.k][tmp.b]){
                    inq[tmp.u][tmp.times][tmp.k][tmp.b] = 1;
                    que.push(tmp);
                }
            }
        }
        if (u != 1 && u != n){
            int cost = d[u][node.times][node.k][node.b];
            tmp.u = u; tmp.k = (node.k+1)%K;
            tmp.times = node.times+1;
            if (tmp.times>T) continue;
            if (node.b+1 <= B && cost-prices[node.k][u] > d[u][tmp.times][tmp.k][node.b+1]){
                d[u][tmp.times][tmp.k][node.b+1] = cost-prices[node.k][u];
                tmp.b = node.b+1;
                if (!inq[tmp.u][tmp.times][tmp.k][tmp.b]){
                    inq[tmp.u][tmp.times][tmp.k][tmp.b] = 1;
                    que.push(tmp);
                }
            }
            if (node.b > 0 && cost+prices[node.k][u] > d[u][tmp.times][tmp.k][node.b-1]){
                d[u][tmp.times][tmp.k][node.b-1] = cost+prices[node.k][u];
                tmp.b = node.b-1;
                if (!inq[tmp.u][tmp.times][tmp.k][tmp.b]){
                    inq[tmp.u][tmp.times][tmp.k][tmp.b] = 1;
                    que.push(tmp);
                }
            }
            tmp.b = node.b;
            if (cost > d[u][tmp.times][tmp.k][tmp.b]){
                d[u][tmp.times][tmp.k][tmp.b] = cost;
                if (!inq[tmp.u][tmp.times][tmp.k][tmp.b]){
                    inq[tmp.u][tmp.times][tmp.k][tmp.b] = 1;
                    que.push(tmp);
                }
            }
        }
    }
    if (!flag) return -1;
    int ans = 0;
    for (int i = 0; i <= T; i++)
        for (int j = 0; j <= B; j++)
            ans = max(ans, d[n][i][0][j]);
    return ans;
}
int kase;
void solve(){
    scanf("%d%d%d%d%d%d", &n, &m, &B, &K, &R, &T);
    memset(head, -1, sizeof(head));
    tot = 0;
    int u, v, tm, cost;
    for (int i = 0; i < K; i++)
        for (int j = 1; j <= n; j++) scanf("%d", &prices[i][j]);
    for (int i = 0; i < m; i++){
        scanf("%d%d%d%d", &u, &v, &tm, &cost);
        addedge(u, v, tm, cost);
    }
    int ans = bfs();
    printf("Case #%d: ", kase);
    if (ans == -1) puts("Forever Alone");
    else printf("%d\n", ans);
}
int main(){
    int cs; scanf("%d", &cs);
    for (kase = 1; kase <= cs; kase++) solve();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值