hdu 4571 Travel in time ( 图论+动态规划 )

来源:互联网 发布:sql调用存储过程 编辑:程序博客网 时间:2024/05/17 23:53

Travel in time

Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 971 Accepted Submission(s): 196


Problem Description
  Bob gets tired of playing games, leaves Alice, and travels to Changsha alone. Yuelu Mountain, Orange Island, Window of the World, the Provincial Museum etc...are scenic spots Bob wants to visit. However, his time is very limited, he can’t visit them all.
  Assuming that there are N scenic spots in Changsha, Bob defines a satisfaction value Si to each spot. If he visits this spot, his total satisfaction value will plus Si. Bob hopes that within the limited time T, he can start at spot S, visit some spots selectively, and finally stop at spot E, so that the total satisfaction value can be as large as possible. It's obvious that visiting the spot will also cost some time, suppose that it takes Ci units of time to visit spot i ( 0 <= i < N ).
  Always remember, Bob can choose to pass by a spot without visiting it (including S and E), maybe he just want to walk shorter distance for saving time.
  Bob also has a special need which is that he will only visit the spot whose satisfaction value isstrictly larger than that of which he visited last time. For example, if he has visited a spot whose satisfaction value is 50, he would only visit spot whose satisfaction value is 51 or more then. The paths between the spots are bi-directional, of course.

Input
  The first line is an integer W, which is the number of testing cases, and the W sets of data are following.
  The first line of each test data contains five integers: N M T S E. N represents the number of spots, 1 < N < 100; M represents the number of paths, 0 < M < 1000; T represents the time limitation, 0 < T <= 300; S means the spot Bob starts from. E indicates the end spot. (0 <= S, E < N)
  The second line of the test data contains N integers Ci ( 0 <= Ci <= T ), which means the cost of time if Bob visits the spot i.
  The third line also has N integers, which means the satisfaction value Si that can be obtained by visiting the spot i ( 0 <= Si < 100 ).
  The next M lines, each line contains three integers u v L, means there is a bi-directional path between spot u and v and it takes L units of time to walk from u to v or from v to u. (0 <= u, v < N, 0 <= L <= T)

Output
  Output case number in the first line (formatted as the sample output).
  The second line contains an integer, which is the greatest satisfaction value.
If Bob can’t reach spot E in T units of time, you should output just a “0” (without quotation marks).

Sample Input
14 4 22 0 31 1 1 15 7 9 120 1 101 3 100 2 102 3 10

Sample Output
Case #1:21

Source
2013 ACM-ICPC长沙赛区全国邀请赛——题目重现

Recommend
zhoujiaqi2010

题意:
n个点m条路组成的无向图。走每一条路都会花一定的时间。参观每一个点对应的顶点也要花一定的时间,每参观
完一个景点会有一个满意度。求在t时间内从起点到达终点且获得的最大满意度。
要求:1、每次访问的景点的满意度必须大于前一次访问的景点获得的满意度。
           2、每个景点都可以选择访问或者只是路过。

分析:
1、由于要求1,必须将景点按照满意度从小到大排序。如果满意度相等,就按编号大小排序。
2、三点式的思维,首先只考虑起点到n个点的时间和满意度,然后通过中间插入其他可以访问的点来更新
      时间和满意度(时间越短越好----最短路的松弛操作,相同时间下满意度越大越好)。这样就把所有可
      能的路径其时间相应的满意度都找到了。最后只要从该点到达终点的时间加上到达该点的时间小于等于
      t就ok了。(首先考虑的相当于到i点并访问,而不路过其他点或者路过的点只是路过不访问的情况)
3、注意的点很多:
      (1)首先是判重。两个点之间可能有多条路。
      (2)其次就是对起点和终点的处理。起点可以访问也可以路过。如果从起点开始用spfa
          则起点是访问了,如果从后一个节点开始spfa则起点是路过。所以要设置一个虚拟
          起点。
      (3)hash数组的使用。
4、状态转移方程:dp[i][k]表示k时间到达i点得到的满意度。
      dp[i][k]=max(dp[i][k],dp[j][k-a[i].c-maps[i][j]]+a[i].v)


代码:
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#define INF 10000000using namespace std;int dp[105][305];int maps[105][105];int hash[105];typedef struct{    int c,v,id;}Point;Point a[105];//按满意度从小到大和编号从小到大排序bool cmp(Point aa,Point bb)       {    if(aa.v!=bb.v) return aa.v<bb.v;    return aa.id<bb.id;}int main(){    int T,n,m,t,s,e,i,j,k,x,y,z,ans,cnt=1;    scanf("%d",&T);    while(T--)    {        scanf("%d%d%d%d%d",&n,&m,&t,&s,&e);        for(i=0;i<n;i++)        {            scanf("%d",&a[i].c);            a[i].id=i;        }        for(i=0;i<n;i++)            scanf("%d",&a[i].v);        sort(a,a+n,cmp);        for(i=0;i<n;i++)            hash[a[i].id]=i;        s=hash[s];        e=hash[e];        for(i=0;i<n;i++)        //初始化任意两点间的距离        {            for(j=0;j<n;j++)            {                //maps[i][i]=0;                if(i==j) maps[i][j]=0;                else maps[i][j]=INF;            }        }        for(i=0;i<m;i++)        {            scanf("%d%d%d",&x,&y,&z);            x=hash[x];            y=hash[y];            maps[x][y]=min(z,maps[x][y]);            maps[y][x]=min(z,maps[y][x]);        }        for(k=0;k<n;k++)         //松弛(spfa更新最短距离)        {            for(i=0;i<n;i++)            {                for(j=0;j<n;j++)                {                    maps[i][j]=min(maps[i][k]+maps[k][j],maps[i][j]);                }            }        }        printf("Case #%d:\n",cnt++);        memset(dp,-1,sizeof(dp));        for(i=0;i<n;i++)      //从虚拟起点开始直接到i点并访问所获得的满意度        {            for(j=a[i].c+maps[i][s];j<=t;j++)     //一直枚举到t。可能经过其他点但是没访问只是路过                dp[i][j]=a[i].v;        }        for(i=0;i<n;i++)        {            for(j=0;j<i;j++)    //如果先经过j点再到i点用时不超过k且满意度大则更新            {                if(a[i].v==a[j].v) break;                for(k=0;k<=t;k++)        //枚举直接到i点是时间k                {                    if(maps[i][j]+a[i].c>k)                        continue;                    if(dp[j][k-maps[i][j]-a[i].c]==-1) continue;                    dp[i][k]=max(dp[i][k],dp[j][k-maps[i][j]-a[i].c]+a[i].v);                }            }        }        ans=0;        for(i=0;i<n;i++)        {            for(j=0;j+maps[i][e]<=t;j++)   //虚拟终点            {                ans=max(ans,dp[i][j]);            }        }        printf("%d\n",ans);    }    return 0;}//AC//609MS



                                   
原创粉丝点击