题目链接:
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; }
来源:https://www.cnblogs.com/pangblog/p/3260682.html