题意:在T秒内从S到E,中间可以参观景点,每个景点有个价值vi,每次只能参观比上次价值大的景点,问最后能获得的最大的价值和是多少。
思路:首先用floyd处理下任意两点的距离。dp[i][j]表示最后到达i点并参观i所在景点时花费了时间j所能获得的最大价值,然后把景点按价值排序,把价值相同的放在一起,剩下就是个分组背包的问题了。。。由于最开始想要直接获得dp的值,要考虑到达i点不参观的情况,可能是写搓了,各种wa,后来一想,直接定义成到达i点并参观完i点的景点的最大价值,这样就好写多了,只要最后算一下从各个点到E的距离就行了。状态的定义和编码复杂度也很有关系啊。。。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<stack> #include<cmath> #include<vector> #define inf 0x3f3f3f3f #define Inf 0x3FFFFFFFFFFFFFFFLL #define eps 1e-9 #define pi acos(-1.0) using namespace std; typedef long long ll; const int maxn=100+10; const int maxt=300+10; int dp[maxn][maxn][maxt],dis[maxn][maxn],vv[maxn],cc[maxn]; int n,m,S,E,T,N; struct Node { int val; vector<int>vt; bool operator <(const Node &a) const { return val<a.val; } }node[maxn],nd[maxn]; void Init() { for(int i=0;i<=n;++i) for(int j=0;j<=n;++j) dis[i][j]=(i==j)?0:inf; for(int i=0;i<maxn;++i) node[i].vt.clear(); } void floyd() { for(int k=0;k<n;++k) 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]); } void solve() { memset(dp,0xff,sizeof(dp)); for(int i=0;i<n;++i) if(dis[S][i]<=T) dp[0][i][dis[S][i]]=0; int u,v,size,t; for(int i=1;i<=N;++i) { for(u=0;u<n;++u) for(int j=0;j<=T;++j) dp[i][u][j]=dp[i-1][u][j]; size=nd[i].vt.size(); for(int k=0;k<size;++k) { v=nd[i].vt[k]; for(int u=0;u<n;++u) for(int j=T;j>=0;--j) { if(dp[i-1][u][j]==-1) continue; t=j+dis[u][v]+cc[v]; if(t<=T) dp[i][v][t]=max(dp[i][v][t],dp[i-1][u][j]+vv[v]); } } } for(u=0;u<n;++u) for(int i=0;i<=T;++i) if(i+dis[u][E]<=T) dp[N][E][i+dis[u][E]]=max(dp[N][u][i],dp[N][E][i+dis[u][E]]); } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int t,tcase=0; scanf("%d",&t); while(t--) { tcase++; scanf("%d%d%d%d%d",&n,&m,&T,&S,&E); Init(); for(int i=0;i<n;++i) scanf("%d",&cc[i]); for(int i=0;i<n;++i) { scanf("%d",&vv[i]); node[i].val=vv[i]; node[i].vt.push_back(i); } sort(node,node+n); N=1; nd[N]=node[0]; int u,v,w; for(int i=1;i<n;++i) { v=node[i].vt[0]; if(nd[N].val==node[i].val) nd[N].vt.push_back(v); else { nd[++N].vt.clear(); nd[N].vt.push_back(v); nd[N].val=node[i].val; } } for(int i=0;i<m;++i) { scanf("%d%d%d",&u,&v,&w); dis[u][v]=dis[v][u]=min(dis[u][v],w); } floyd(); solve(); int ans=0; for(int i=0;i<=T;++i) ans=max(ans,dp[N][E][i]); printf("Case #%d:\n%d\n",tcase,ans); } return 0; }