题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=203
思路:先求点0到每个点的最短距离,dijkstra算法,然后就是01背包了
我奇怪的是100*1000000的时间复杂度居然没有超时!
代码如下:
#include "stdio.h" #include "string.h" #define N 105 #define INF 0x3fffffff bool mark[N]; int dist[N]; int map[N][N]; int dp[1000005]; void Init(int n) { for(int i=0; i<=n; ++i) { for(int j=0; j<=n; ++j) map[i][j] = INF; } } void dij(int n) { int i,j,k; memset(mark,false,sizeof(mark)); for(i=0; i<=n; ++i) dist[i] = map[0][i]; mark[0] = true; int mint; for(i=1; i<=n; ++i) { k = 0; mint = INF; for(j=0; j<=n; ++j) { if(!mark[j] && mint>dist[j]) { mint = dist[j]; k = j; } } mark[k] = true; for(j=0; j<=n; ++j) { if(!mark[j] && dist[j]>dist[k]+map[k][j]) dist[j] = dist[k]+map[k][j]; } } } int value[N]; int main() { int T; int n,sum,m; int i,j; int x,y,k; scanf("%d",&T); while(T--) { scanf("%d %d %d",&sum,&n,&m); Init(n); while(m--) { scanf("%d %d %d",&x,&y,&k); if(k<map[x][y]) map[x][y] = map[y][x] = k; } for(i=1; i<=n; ++i) scanf("%d",&value[i]); dij(n); memset(dp,0,sizeof(dp)); for(i=1; i<=n; ++i) //01背包 { for(j=sum; j>=dist[i]; j--) { if(dp[j] < dp[j-dist[i]] + value[i]) dp[j] = dp[j-dist[i]]+value[i]; } } int ans = 0; for(i=1; i<=sum; ++i) ans = ans>dp[i]?ans:dp[i]; printf("%d ",ans); } return 0; }