大意:n个点(时间消耗,满意值),m条边(起点,终点,消耗的时间),时限T,旅途的起点,终点.
每个点你可以选择参观和不参观(包括起点终点),如果你选择参观某个点,那满意值一定要大于上一次参观的,最后整个旅途的最大满意值
想法:先用floyd求出每两个点的最短距离,然后就是dp了.
以前就Wa了,今天看着学长的代码,发现了自己的错误,他只要求参观的点的满意值递增,所以我们的可以经过的点不是在排序后的[S,E]里,所有点都有可能.
还有就是从dp[i][k]推到dp[j][k+map[i][j]+j.c]时,要判断dp[i][k]这个状态是否已经达到了.
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
inline int input()
{
int ret=0;bool IsN=0;char c=getchar();
while(c<'0'||c>'9') {if(c=='-') IsN=1;c=getchar();}
while(c>='0'&&c<='9') ret=ret*10+c-'0',c=getchar();
return IsN?-ret:ret;
}
#define N 105
#define T 305
#define INF 100000000
struct node
{
int c,w,ind;
}p[N];
bool cmp(node i,node j)
{
return i.w<j.w;
}
int map[N][N],dp[N][T],id[N];
int Ca,n,m,t,s,e;
int x,y,z;
bool vis[N];
inline void floyd()
{
for(int k=0;k<n;k++)
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
}
}
}
int main()
{
Ca=input();
for(int ca=1;ca<=Ca;ca++)
{
n=input(),m=input(),t=input(),s=input(),e=input();
for(int i=0;i<n;i++) p[i].c=input();
for(int i=0;i<n;i++) p[i].w=input();
for(int i=0;i<n;i++) p[i].ind=i;
sort(p,p+n,cmp);
for(int i=0;i<n;i++)
{
id[p[i].ind]=i;
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++) map[i][j]=(i==j?0:INF);
for(int i=0;i<m;i++)
{
x=input(),y=input(),z=input();
x=id[x],y=id[y];
map[x][y]=map[y][x]=min(map[y][x],z);
}
s=id[s],e=id[e];
floyd();
memset(dp,-1,sizeof(dp));
for(int i=0;i<n;i++)
{
for(int j=p[i].c+map[i][s];j<=t;j++)
dp[i][j]=p[i].w;
}
for(int i=0;i<n;i++)
{
for(int j=0;j<i;j++)
{
if(map[i][j]==INF) continue;
if(p[i].w==p[j].w) continue;
for (int k=0;k<=t;k++)
{
if (dp[j][k]==-1) continue;
if(k+map[i][j]+p[i].c<=t)
dp[i][k+map[i][j]+p[i].c]=max(dp[i][k+map[i][j]+p[i].c],dp[j][k]+p[i].w);
}
}
}
int ans=0;
for(int i=0;i<n;i++)
{
for(int j=0;j+map[i][e]<=t;j++)
{
ans=max(ans,dp[i][j]);
}
}
printf("Case #%d:\n%d\n",ca,ans);
}
}