floyd+动态规划 hdu-4571-Travel in time

题目链接:

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

题目大意:

有n个景点,每个点都有个游玩时间ci,游玩后得到的满意度si。给一个起点s和终点e,两个景点间有条无向边,权值为时间。从起点出发,在给定时间限制下,到达终点,问能获得的最大的满意值,只有游玩了景点才能获得该景点的满意值,并且上个游玩景点的满意度必须大于后一个游玩的景点满意度。

解题思路:

图上的dp.

见到图论就晕啊啊啊。先求出不游玩时,任意两点的到达时间,用floyd求。

dp[i][j]表示到达第i个点,用时为j时,能到达的最大的满意度。

本题的关键是先对每个景点的满意度从小到大排序,然后对于第i个景点枚举时间j(从大到小,因为一个景点只能游一次), 在枚举前面的i-1个景点,通过前面的满意度得出当前的满意度。转移方程还是很好写的。

代码:

 

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF 0x1f1f1f1f
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

/*
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
*/
#define Maxn 110
int dp[Maxn][310]; //dp[i][j]表示到达第i个点花了j时间的能获得的最大满意度
int dis[Maxn][Maxn]; //任意两点间的距离
int n,m;

struct Node
{
   int id,si,ci;
   friend bool operator < (const struct Node &a,const struct Node &b)
   {
      return a.si<b.si; //按满意度从小到大排序
   }
}node[Maxn];

void floy()
{
   for(int i=0;i<n;i++)
      for(int j=0;j<n;j++)
      {
         if(i==j)
            dis[i][j]=0; //不游玩的到达时间
         else
            dis[i][j]=INF;
      }
   int a,b,v;
   for(int i=0;i<m;i++)
   {
      scanf("%d%d%d",&a,&b,&v); //注意有重边
      dis[a][b]=dis[b][a]=min(dis[a][b],v);
   }

   for(int k=0;k<n;k++) //floyd 不断更新两点间的距离
      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]);
         }
   return ;
}

int main()
{
   int tt,s,e,t;
   int ca=0;

   scanf("%d",&tt);
   while(tt--)
   //while(~scanf("%d%d%d%d%d",&n,&m,&t,&s,&e))
   {
      scanf("%d%d%d%d%d",&n,&m,&t,&s,&e);
      for(int i=0;i<n;i++)
      {
         scanf("%d",&node[i].ci);
         node[i].id=i;
      }
      for(int i=0;i<n;i++)
         scanf("%d",&node[i].si);
      sort(node,node+n);
      floy();

      printf("Case #%d:\n",++ca);
      if(dis[s][e]>t) //起点不能到达终点或到达时间超过了
      {
         puts("0");
         continue;
      }
      memset(dp,-1,sizeof(dp));
      int ans=0;
      for(int i=0;i<n;i++) //初始化
      {
         if(dis[s][node[i].id]+node[i].ci<=t)
         {
            dp[node[i].id][node[i].ci+dis[s][node[i].id]]=node[i].si;
           // dp[node[i].id][dis[node[s].id][node[i].id]]=0;
         }
         if(t-dis[s][node[i].id]-node[i].ci>=dis[node[i].id][e])
            ans=max(ans,node[i].si);
      }

      for(int i=1;i<n;i++)
         for(int j=t;j>=0;j--)
         {
            for(int k=0;k<i;k++)
            {
               int tmp=j-node[i].ci-dis[node[k].id][node[i].id]; //注意是严格大于
               if(tmp>=0&&node[i].si>node[k].si&&dp[node[k].id][tmp]!=-1)
                  dp[node[i].id][j]=max(dp[node[i].id][j],dp[node[k].id][tmp]+node[i].si);
            }
            if(t-j>=dis[node[i].id][e]) //该点的所有时间都求完了
               ans=max(ans,dp[node[i].id][j]);
         }
      printf("%d\n",ans);
   }
   return 0;
}



 


 

posted @ 2013-08-15 19:41  pangbangb  阅读(185)  评论(0编辑  收藏  举报