hdu 4571 floyd+动态规划

思路:

我们先求一遍floyd,将各点的最短距离求出,然后将点按si的升序排序。dp[i][k]表示第i个点在第j时间所获得的最大效益,那么

dp[i][k]=max(dp[ i ][ k ]  ,  dp[ j ][ k-p[ i ].c-dis[ i ][ j ] ]+p[ i ].s);     dis[i][j]为i与j的最短路径。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 1<<28
using namespace std;
struct Point{
    int c,s,num;
    int operator <(const Point &temp) const
    {
        return s<temp.s;
    }
}p[110];
int dp[110][310],dis[110][110],S,E,n,m,t;
void floyd()
{
    int i,j,k;
    for(k=1;k<=n;k++)
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    return ;
}
void init()
{
    int i,j;
    memset(dp,-1,sizeof(dp));
    for(i=0;i<=109;i++)
    {
        for(j=0;j<=109;j++)
            dis[i][j]=inf;
        dis[i][i]=0;
    }
}
int main()
{
    //freopen("test.txt","r",stdin);
    //freopen("ans.txt","w",stdout);
    int w,i,j,Case=0,a,b,v;
    scanf("%d",&w);
    while(w--)
    {
        init();
        scanf("%d%d%d%d%d",&n,&m,&t,&S,&E);
        S++;
        E++;
        for(i=1;i<=n;i++)
            scanf("%d",&p[i].c);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&p[i].s);
            p[i].num=i;
        }
        for(i=1;i<=m;i++)
        {
            scanf("%d%d%d",&a,&b,&v);
            a++,b++;
            dis[a][b]=dis[b][a]=min(dis[a][b],v);
        }
        floyd();
        p[0]=p[S];//将p[0]设为虚的起始点
        sort(p+1,p+n+1);
        for(i=0;i<=n;i++)
        {
            for(j=p[i].c+dis[p[i].num][S];j<=t;j++)
                dp[i][j]=p[i].s;
        }
        int k;
        for(i=1;i<=n;i++)
        {
            for(j=0;j<i;j++)
            {
                if(p[i].s>p[j].s)
                for(k=t;k>=p[i].c+dis[p[i].num][p[j].num]&&k>=0;k--)
                {
                    if(dp[j][k-p[i].c-dis[p[i].num][p[j].num]]!=-1)
                    dp[i][k]=max(dp[i][k],dp[j][k-p[i].c-dis[p[i].num][p[j].num]]+p[i].s);
                }
            }
        }
        for(i=1;i<=n;i++)
        {
            if(p[i].num==E)
                break;
        }
        int ans=0;
        for(j=0;j<=n;j++)
        {
                for(k=0;k<=t;k++)
                {
                    if(k+dis[p[j].num][E]>t)
                        break;
                    ans=max(ans,dp[j][k]);
                }
        }
        printf("Case #%d:\n%d\n",++Case,ans);
    }
    return 0;
}

 

posted @ 2013-07-18 19:44  fangguo  阅读(206)  评论(0编辑  收藏  举报