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

来源:互联网 发布:我的世界掉落优化mod 编辑:程序博客网 时间:2024/05/17 21:46

题目链接:

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 110int 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;}



原创粉丝点击