HDU 4571 Travel in time

18 篇文章 0 订阅
本文详细介绍了HDU 4571编程题的题意、解题思路及完整代码,帮助读者理解并解决该问题。
摘要由CSDN通过智能技术生成

题目:

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

题意:

有n个景点,互相之间有一些路,每条路都有耗时,游玩每个景点也有一个耗时,游玩每个景点之后会获得一个满意度,现在要从给定的s景点走到e景点,要求在t时间内获得最大的满意度,且游玩当前景点能够获得的满意度必须大于前一个景点时才能游玩。

思路:

因为游玩的下一个景点的满意度一定大于当前景点,所以大大简化了这道题,各景点之间的游玩顺序一定是绝对的,所有就从TSP简化成了单向的dp,只要判断每个景点是否游玩就行了,所以就是01背包,只要提前floyd预处理所有点之间的最短距离,然后背包dp就行了。还有因为给定了起点和终点,所以预处理每个点的起始值时耗时是g[i][s],并且最后的结果也是所有点每个时间加上g[i][e]也就是走回e点是最终耗时,这样的话就不用特判s,e点了,它们本身到起始/终止点的耗时是0.

代码:

#define N 112

int n,m,s,e,maxx;
int flag,sum,ave,ans,res,len,ans1,ans2;
int g[N][N],a[N];
int dp[N][5*N];
struct node
{
    int x,y,r;
    friend bool operator < (node a, node b)
    {
        return a.r < b.r;
    }
}tn[N];
void init(int n)
{
    memset(g,0x3f,sizeof(g));
    for(int i=0;i<n;i++)
        g[i][i] = 0;
}
void floyd(int n)
{
    for(int k=0;k<n;k++)
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                g[i][j] = min(g[i][j],g[i][k]+g[k][j]);
}
int main()
{
    int T,cas,i,j,k,x,y,z,t;
    scanf("%d",&T);
    cas=0;
    while(T--)
    {
        scanf("%d%d%d%d%d",&n,&m,&maxx,&s,&e);
        sum=0;
        for(i=0;i<n;i++)
        {
            scanf("%d",&tn[i].x);
            tn[i].y=i;
        }
        for(i=0;i<n;i++)
            scanf("%d",&tn[i].r);
        sort(tn,tn+n);
        for(i=0;i<n;i++)
            a[tn[i].y] = i;

        init(n);
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            g[a[x]][a[y]]=g[a[y]][a[x]]=min(z,g[a[x]][a[y]]);
        }
        floyd(n);
        s=a[s];e=a[e];

        memset(dp,-1,sizeof(dp));
        for(i=0;i<n;i++)
            for(j=tn[i].x+g[i][s];j<=maxx;j++)
                dp[i][j] = tn[i].r;
        for(i=0;i<n;i++)
            for(j=0;j<i;j++)
                if(tn[i].r>tn[j].r)
                    for(k=g[i][j]+tn[i].x;k<=maxx;k++)
                        if(dp[j][k-g[i][j]-tn[i].x]!=-1)
                            dp[i][k] = max(dp[i][k],dp[j][k-g[i][j]-tn[i].x]+tn[i].r);
        res=0;
        for(i=0;i<n;i++)
            for(j=0;j+g[i][e]<=maxx;j++)
                res=max(res,dp[i][j]);
        printf("Case #%d:\n%d\n",++cas,res);
    }
    return 0;
}










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值