hdu 4571 Travel in time (floyd+分组背包)

来源:互联网 发布:王者荣耀美化软件 编辑:程序博客网 时间:2024/06/05 02:52

题意:在T秒内从S到E,中间可以参观景点,每个景点有个价值vi,每次只能参观比上次价值大的景点,问最后能获得的最大的价值和是多少。

思路:首先用floyd处理下任意两点的距离。dp[i][j]表示最后到达i点并参观i所在景点时花费了时间j所能获得的最大价值,然后把景点按价值排序,把价值相同的放在一起,剩下就是个分组背包的问题了。。。由于最开始想要直接获得dp的值,要考虑到达i点不参观的情况,可能是写搓了,各种wa,后来一想,直接定义成到达i点并参观完i点的景点的最大价值,这样就好写多了,只要最后算一下从各个点到E的距离就行了。状态的定义和编码复杂度也很有关系啊。。。

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=100+10;const int maxt=300+10;int dp[maxn][maxn][maxt],dis[maxn][maxn],vv[maxn],cc[maxn];int n,m,S,E,T,N;struct Node{    int val;    vector<int>vt;    bool operator <(const Node &a) const    {        return val<a.val;    }}node[maxn],nd[maxn];void Init(){    for(int i=0;i<=n;++i)        for(int j=0;j<=n;++j)            dis[i][j]=(i==j)?0:inf;    for(int i=0;i<maxn;++i)        node[i].vt.clear();}void floyd(){    for(int k=0;k<n;++k)        for(int i=0;i<n;++i)            for(int j=0;j<n;++j)                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);}void solve(){    memset(dp,0xff,sizeof(dp));    for(int i=0;i<n;++i) if(dis[S][i]<=T) dp[0][i][dis[S][i]]=0;    int u,v,size,t;    for(int i=1;i<=N;++i)    {        for(u=0;u<n;++u)            for(int j=0;j<=T;++j)                dp[i][u][j]=dp[i-1][u][j];        size=nd[i].vt.size();        for(int k=0;k<size;++k)        {            v=nd[i].vt[k];            for(int u=0;u<n;++u)                for(int j=T;j>=0;--j)                {                    if(dp[i-1][u][j]==-1) continue;                    t=j+dis[u][v]+cc[v];                    if(t<=T)                        dp[i][v][t]=max(dp[i][v][t],dp[i-1][u][j]+vv[v]);                }        }    }    for(u=0;u<n;++u)        for(int i=0;i<=T;++i)            if(i+dis[u][E]<=T)  dp[N][E][i+dis[u][E]]=max(dp[N][u][i],dp[N][E][i+dis[u][E]]);}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int t,tcase=0;    scanf("%d",&t);    while(t--)    {        tcase++;        scanf("%d%d%d%d%d",&n,&m,&T,&S,&E);        Init();        for(int i=0;i<n;++i)            scanf("%d",&cc[i]);        for(int i=0;i<n;++i)        {            scanf("%d",&vv[i]);            node[i].val=vv[i];            node[i].vt.push_back(i);        }        sort(node,node+n);        N=1;        nd[N]=node[0];        int u,v,w;        for(int i=1;i<n;++i)        {            v=node[i].vt[0];            if(nd[N].val==node[i].val)                nd[N].vt.push_back(v);            else            {                nd[++N].vt.clear();                nd[N].vt.push_back(v);                nd[N].val=node[i].val;            }        }        for(int i=0;i<m;++i)        {            scanf("%d%d%d",&u,&v,&w);            dis[u][v]=dis[v][u]=min(dis[u][v],w);        }        floyd();        solve();        int ans=0;        for(int i=0;i<=T;++i)            ans=max(ans,dp[N][E][i]);        printf("Case #%d:\n%d\n",tcase,ans);    }    return 0;}

0 0