HDU 4571 - Travel in time(Floyd+dijkstra+dp)

来源:互联网 发布:winscp linux版 编辑:程序博客网 时间:2024/05/22 13:16

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=4571

题意:

N个点M条边时限T,起点S终点E。

每个点都有其参观获得值以及花费,经过是可以选择参观或者是不参观,且下一个参观的地点价值比上一个要大。

M条无向边,每条边都有时间花费。

求出在时限内从起点到终点的所得最大值。

思路:

一次floyd,求出各点中间的最短路,为的是重新建有向图,因为参观地点的顺序是有要求的,符合要求的两个点连边。

须建源点和汇点,以解决参观或不参观的问题。

dp【i】【j】表示到i个点时间花费为j是的最大价值。在dijkstra中跑。

比赛时的想法是dp【i】【0/1】表示在i点取或者不取,但是状态太多,改了很久超时和爆内存。。。

AC.

#include <iostream>#include <cstdio>#include <vector>#include <cstring>#include <queue>using namespace std;const int INF = 0x3f3f3f3f;const int maxn = 150;int N, M, T, S, E;int cost[maxn], valu[maxn];int dist[maxn][maxn];struct edge {    int to, c;    edge(int tt, int cc) {        to = tt; c = cc;    }};vector<edge> g[maxn];void init(){    memset(dist, 0x3f, sizeof(dist));    for(int i = 0; i <= N; ++i) {        dist[i][i] = 0;    }}void floyd(){     for(int k = 0; k < N; ++k) {        for(int i = 0; i < N; ++i){            for(int j = 0; j < N; ++j) {                dist[i][j] = min(dist[i][j], dist[i][k]+dist[k][j]);            }        }    }}typedef pair<int, int> pir;int dp[maxn][maxn*3];void dij(){    priority_queue<pir, vector<pir>, greater<pir> > que;    memset(dp, 0, sizeof(dp));    que.push(pir(0, N));    dp[N][0] = 0;    while(!que.empty()) {        pir p = que.top(); que.pop();        int v = p.second, cv = p.first;        for(int i = 0; i < g[v].size(); ++i) {            edge e = g[v][i];            int cnt = cv + e.c + cost[e.to];            if(cnt <= T && dp[e.to][cnt] < dp[v][cv] + valu[e.to]) {                dp[e.to][cnt] = dp[v][cv] + valu[e.to];                que.push(pir(cnt, e.to));            }        }    }    int ans = 0;    for(int i = 0; i <= T; ++i) {        ans = max(ans, dp[N+1][i]);    }    printf("%d\n", ans);}void build(){    for(int i = 0; i <= N+1; ++i) {        g[i].clear();    }    for(int i = 0; i < N;  ++i) {        for(int j = 0; j < N; ++j) {            if(dist[i][j] != INF) {                if(valu[i] < valu[j]) g[i].push_back(edge(j, dist[i][j]));                //else g[j].push_back(edge(i, dist[i][j]));            }        }    }    for(int i = 0; i < N; ++i) {        if(i == S) {            g[N].push_back(edge(S, 0));        }        else {            g[N].push_back(edge(i, dist[S][i]));        }        if(i == E) {            g[E].push_back(edge(N+1, 0));        }        else {            g[i].push_back(edge(N+1, dist[i][E]));        }    }}int main(){    //freopen("in", "r", stdin);    int Cas;    scanf("%d", &Cas);    for(int cas = 1; cas <= Cas; ++cas) {        scanf("%d %d %d %d %d", &N, &M, &T, &S, &E);        for(int i = 0; i < N; ++i) {            scanf("%d", &cost[i]);        }        for(int i = 0; i < N; ++i) {            scanf("%d", &valu[i]);        }        init();        for(int i = 0; i < M; ++i) {            int u, v, c;            scanf("%d%d%d", &u, &v, &c);            dist[u][v] = min(dist[u][v], c);            dist[v][u] = min(dist[v][u], c);        }        printf("Case #%d:\n", cas);        floyd();        build();        dij();    }    return 0;}


0 0