思路:
我们先求一遍floyd,将各点的最短距离求出,然后将点按si的升序排序。dp[i][k]表示第i个点在第j时间所获得的最大效益,那么
dp[i][k]=max(dp[ i ][ k ] , dp[ j ][ k-p[ i ].c-dis[ i ][ j ] ]+p[ i ].s); dis[i][j]为i与j的最短路径。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define inf 1<<28 using namespace std; struct Point{ int c,s,num; int operator <(const Point &temp) const { return s<temp.s; } }p[110]; int dp[110][310],dis[110][110],S,E,n,m,t; void floyd() { int i,j,k; for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1;j<=n;j++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); return ; } void init() { int i,j; memset(dp,-1,sizeof(dp)); for(i=0;i<=109;i++) { for(j=0;j<=109;j++) dis[i][j]=inf; dis[i][i]=0; } } int main() { //freopen("test.txt","r",stdin); //freopen("ans.txt","w",stdout); int w,i,j,Case=0,a,b,v; scanf("%d",&w); while(w--) { init(); scanf("%d%d%d%d%d",&n,&m,&t,&S,&E); S++; E++; for(i=1;i<=n;i++) scanf("%d",&p[i].c); for(i=1;i<=n;i++) { scanf("%d",&p[i].s); p[i].num=i; } for(i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&v); a++,b++; dis[a][b]=dis[b][a]=min(dis[a][b],v); } floyd(); p[0]=p[S];//将p[0]设为虚的起始点 sort(p+1,p+n+1); for(i=0;i<=n;i++) { for(j=p[i].c+dis[p[i].num][S];j<=t;j++) dp[i][j]=p[i].s; } int k; for(i=1;i<=n;i++) { for(j=0;j<i;j++) { if(p[i].s>p[j].s) for(k=t;k>=p[i].c+dis[p[i].num][p[j].num]&&k>=0;k--) { if(dp[j][k-p[i].c-dis[p[i].num][p[j].num]]!=-1) dp[i][k]=max(dp[i][k],dp[j][k-p[i].c-dis[p[i].num][p[j].num]]+p[i].s); } } } for(i=1;i<=n;i++) { if(p[i].num==E) break; } int ans=0; for(j=0;j<=n;j++) { for(k=0;k<=t;k++) { if(k+dis[p[j].num][E]>t) break; ans=max(ans,dp[j][k]); } } printf("Case #%d: %d ",++Case,ans); } return 0; }