DP——HDU 4571

  • 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4571

  • 题意:给出一个无向图(N个点,M条边,有重边),每条边有一个花费,每个节点有一个花费和一个价值(如果想获得价值,则必须付出花费,否则可以不用付出花费),求从点S到点E,在总花费不超过T的情况下的最大价值是多少

  • 分析:我们设置一个虚拟起点和一个虚拟终点,花费都为0,起点的价值为-1(保证任意点的价值都大于它),终点的价值为一个大数。然后起点到S的距离为0,到其它点的距离和到S一样;E到终点的距离为0,其它点到终点的距离和到E一样。设置DP[i][j]表示访问到点i并付出花费获得i点价值时,总花费为j的最大收获值。那么我们初始化DP[虚拟起点][0]为0,其它DP值为-1。那么只有当DP值不等于-1时,说明这个状态可抵达,我们就从这个状态继续往后扩展,找到能访问的点。

int c = cost[v]+MAP[u][v]+j;
//cout << u << "-" << v << " : " << MAP[u][v] << endl;
if(value[v]>value[u] && c<=T)
{
    DP[v][c] = max(DP[v][c], DP[u][j]+value[v]);
}
  • AC 代码:
/*************************************************************************
    > File Name: test.cpp
    > Author: Akira 
    > Mail: qaq.febr2.qaq@gmail.com 
 ************************************************************************/

#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <bitset>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <set>
#include <list>
#include <ctime>
#include <climits>
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) ((a)*(a))
using namespace std;

#define MaxN 105
#define MaxM MaxN*10
#define INF 0x3f
#define PI 3.1415926535897932384626
const int mod = 1E9+7;
const double eps = 1e-6;
#define bug cout<<88888888<<endl;
#define debug(x) cout << #x" = " << x << endl;
int BigBang = 1000000;
int N,M,T,S,E;
int cost[MaxN],value[MaxN];
int MAP[MaxN][MaxN];
struct Scen 
{
    int id;
}ss[MaxN];
void Floyd()
{
    for(int k=0;k<N;k++)
        for(int i=0;i<N;i++)
            for(int j=0;j<N;j++)
                MAP[i][j] = min(MAP[i][j], MAP[i][k]+MAP[k][j]);
}
int DP[MaxN][3*MaxN];
int Begin;
int End;
int len;
void solve(int t)
{   
    //debug(MAP[S][E]);
    MST(DP,-1);
    DP[Begin][0] = 0;
    for(int i=0;i<len;i++)
    {
        int u = ss[i].id;
        for(int j=0;j<=T;j++)
        {
            if(DP[u][j]!=-1)
            {
                for(int k=i+1;k<len;k++)
                {
                    int v = ss[k].id;
                    int c = cost[v]+MAP[u][v];
                    if(value[v]>value[u] && j+c<=T)
                    {
                        DP[v][j+c] = max(DP[v][j+c], DP[u][j]+value[v]);
                    }
                }
            }
        }
    }
    int ans = BigBang;
    for(int j=0;j<=T;j++) ans = max(ans, DP[End][j]); 
    ans -= BigBang;
    printf("Case #%d:\n%d\n", t, ans);
}
int main()
{
    //std::ios::sync_with_stdio(false);
    int W;
    scanf("%d", &W);
    for(int t=1;t<=W;t++)
    {
        MST(MAP,INF);
        scanf("%d%d%d%d%d", &N, &M, &T, &S, &E);
        len = 0;
        Begin = N+1, End = N;
        cost[Begin] = cost[End] = 0, value[Begin] = -1, value[End] = BigBang;
        ss[len++].id = Begin,ss[len++].id = End;
        for(int i=0;i<N;i++) scanf("%d", &cost[i]);
        for(int i=0;i<N;i++) 
        {
            scanf("%d", &value[i]);
            ss[len++].id = i;
        }

        sort(ss,ss+len,[](Scen a, Scen b){return value[a.id]<value[b.id];});
        int u,v,L;
        while(M--)
        {
            scanf("%d%d%d", &u, &v, &L);
            MAP[u][v] = MAP[v][u] = min(L, MAP[u][v]);
        }
        Floyd();
        for(int i=0;i<N;i++)
        {
            MAP[Begin][i] = MAP[S][i];
            MAP[i][End] = MAP[i][E];
        }
        MAP[Begin][End] = MAP[S][E];
        MAP[Begin][S] = MAP[E][End] = 0;
        solve(t);
    }
    //system("pause");
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值