题意:一些点,之间有双向边,每个点可以获得一个si值,但是也要付出相应ci的代价,你可以只经过那个点但是不获得那个si值,每次获得的si值要满足,大于最近一次获得的si值,也可以说,获得si值的顺序是严格从小到大的。
做的时候,先要考虑构造dp的模型,dp[i][j]就是时间为i最近一次是获得sj的值,此时获取的si的总值。初始化考虑是否获得初始点S的si值,求答案时,考虑是否获得E的si值,其实就是一样的,考虑是否获得每个点的si值作为初始化,考虑最后一次为是否获得每个点的si值做为最终答案,也就是两个循环的事。
坑来了。坑在ci可能为0,也就是说,如果你直接背包同一个t的状态可能有的先背有的后背,不同背的顺序得到的答案就会前后不一致。那么就对si排序,保证顺序是按照si来的,这样不管先背后备,就是按照si背的,不会有错。
还有一个坑,紫书的floyed打印错了,导致直接wa的没想法。
大概就是这些要注意的了。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 301;
int dp[333][111];
int dis[111][111];
int Ci[111],Si[111];
struct Node{
int o;
bool operator < (const Node&rhs)const{
return Si[o]<Si[rhs.o];
}
}mp[111];
int main()
{
// freopen("data.in","r",stdin);
int W,cas=1,ans,N,M,T,S,E,u,v,l;
scanf("%d",&W);
while(W--){
scanf("%d%d%d%d%d",&N,&M,&T,&S,&E);
for(int i=0;i<N;i++)
scanf("%d",&Ci[i]);
for(int i=0;i<N;i++)
scanf("%d",&Si[i]);
for(int i=0;i<N;i++)
mp[i].o = i;
sort(mp,mp+N);
for(int i=0;i<N;i++)
for(int j=0;j<N;j++){
dis[i][j]=INF;
if(i==j) dis[i][j] = 0;
}
while(M--){
scanf("%d%d%d",&u,&v,&l);
if(dis[u][v]>l){
dis[u][v] = l;
dis[v][u] = l;
}
}
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
for(int k=0;k<N;k++)
if(dis[j][i]<=T && dis[i][k]<=T)
dis[j][k] = min(dis[j][k],dis[j][i]+dis[i][k]);
memset(dp,-1,sizeof dp);
for(int i=0;i<N;i++)
if(Ci[i]+dis[S][i] <= T)
dp[Ci[i]+dis[S][i]][i] = Si[i];
// for(int i=0;i<=T;i++)
// for(int j=0;j<N;j++){
// int mj = mp[j].o;
// for(int k=0;k<N;k++){
// int mk = mp[k].o;
// if(i - dis[mk][mj] - Ci[mj] >= 0 && dp[i - dis[mk][mj] - Ci[mj]][mk]!=-1){
// if(Si[mk] < Si[mj]){
// if(dp[i][mj]==-1 || dp[i][mj] < dp[i - dis[mk][mj] - Ci[mj]][mk] + Si[mj]){
// dp[i][mj] = dp[i - dis[mk][mj] - Ci[mj]][mk] + Si[mj];
// }
// }
// }
// }
// }
for(int i=0;i<=T;i++)
for(int j=0;j<N;j++){
int mj = mp[j].o;
if(dp[i][mj] == -1) continue;
for(int k=0;k<N;k++){
int mk = mp[k].o;
if(Si[mj] < Si[mk] && i + dis[mj][mk] + Ci[mk] <= T){
if(dp[i + dis[mj][mk] + Ci[mk]][mk]==-1 || dp[i + dis[mj][mk] + Ci[mk]][mk] < dp[i][mj] + Si[mk]){
dp[i + dis[mj][mk] + Ci[mk]][mk] = dp[i][mj] + Si[mk];
}
}
}
}
ans=0;
for(int j=0;j<N;j++)
for(int i=0;i<=T-dis[j][E];i++)
ans = max(ans,dp[i][j]);
printf("Case #%d:\n",cas++);
printf("%d\n",ans);
}
return 0;
}