这题 不会写啊 虽然题意明白了 方法大概知道 但是状态有点难表示啊 啊 啊...
放个 题解链接 大概看懂了 主要是dp初始化没想到 自己一般都只是个Memset之后 就是对于1 2个点的特别初始化了 没有想到过对于其它所有点的状态表示就是1-n的
代码 放出来 方便看.~

1 #include<iostream> 2 #include<cmath> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<string> 6 #include<cstring> 7 #include<algorithm> 8 #include<vector> 9 #include<map> 10 #include<set> 11 #include<stack> 12 #include<list> 13 #include<queue> 14 #define eps 1e-6 15 #define INF 0x1f1f1f1f 16 #define PI acos(-1.0) 17 #define ll __int64 18 #define lson l,m,(rt<<1) 19 #define rson m+1,r,(rt<<1)|1 20 //#pragma comment(linker, "/STACK:1024000000,1024000000") 21 using namespace std; 22 23 /* 24 freopen("data.in","r",stdin); 25 freopen("data.out","w",stdout); 26 */ 27 #define Maxn 110 28 int dp[Maxn][310]; //dp[i][j]表示到达第i个点花了j时间的能获得的最大满意度 29 int dis[Maxn][Maxn]; //任意两点间的距离 30 int n,m; 31 32 struct Node 33 { 34 int id,si,ci; 35 friend bool operator < (const struct Node &a,const struct Node &b) 36 { 37 return a.si<b.si; //按满意度从小到大排序 38 } 39 }node[Maxn]; 40 41 void floy() 42 { 43 for(int i=0;i<n;i++) 44 for(int j=0;j<n;j++) 45 { 46 if(i==j) 47 dis[i][j]=0; //不游玩的到达时间 48 else 49 dis[i][j]=INF; 50 } 51 int a,b,v; 52 for(int i=0;i<m;i++) 53 { 54 scanf("%d%d%d",&a,&b,&v); //注意有重边 55 dis[a][b]=dis[b][a]=min(dis[a][b],v); 56 } 57 58 for(int k=0;k<n;k++) //floyd 不断更新两点间的距离 59 for(int i=0;i<n;i++) 60 for(int j=0;j<n;j++) 61 { 62 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); 63 } 64 return ; 65 } 66 67 int main() 68 { 69 int tt,s,e,t; 70 int ca=0; 71 72 scanf("%d",&tt); 73 while(tt--) 74 //while(~scanf("%d%d%d%d%d",&n,&m,&t,&s,&e)) 75 { 76 scanf("%d%d%d%d%d",&n,&m,&t,&s,&e); 77 for(int i=0;i<n;i++) 78 { 79 scanf("%d",&node[i].ci); 80 node[i].id=i; 81 } 82 for(int i=0;i<n;i++) 83 scanf("%d",&node[i].si); 84 sort(node,node+n); 85 floy(); 86 87 printf("Case #%d: ",++ca); 88 if(dis[s][e]>t) //起点不能到达终点或到达时间超过了 89 { 90 puts("0"); 91 continue; 92 } 93 memset(dp,-1,sizeof(dp)); 94 int ans=0; 95 for(int i=0;i<n;i++) //初始化 96 { 97 if(dis[s][node[i].id]+node[i].ci<=t) 98 { 99 dp[node[i].id][node[i].ci+dis[s][node[i].id]]=node[i].si; 100 // dp[node[i].id][dis[node[s].id][node[i].id]]=0; 101 } 102 if(t-dis[s][node[i].id]-node[i].ci>=dis[node[i].id][e]) 103 ans=max(ans,node[i].si); 104 } 105 106 for(int i=1;i<n;i++) 107 for(int j=t;j>=0;j--) 108 { 109 for(int k=0;k<i;k++) 110 { 111 int tmp=j-node[i].ci-dis[node[k].id][node[i].id]; //注意是严格大于 112 if(tmp>=0&&node[i].si>node[k].si&&dp[node[k].id][tmp]!=-1) 113 dp[node[i].id][j]=max(dp[node[i].id][j],dp[node[k].id][tmp]+node[i].si); 114 } 115 if(t-j>=dis[node[i].id][e]) //该点的所有时间都求完了 116 ans=max(ans,dp[node[i].id][j]); 117 } 118 printf("%d ",ans); 119 } 120 return 0; 121 }
/*******/
洗个澡 想明白了很多 .-大致说下步骤
首先 floyd预处理任意两个点间的最短距离 然后就是最重要的 for遍历所有城市节点 初始化从该S点出发到该点的dp[][]状态
这边 主要是初始化. 所以其实
1 for(int i=0;i<n;i++) //初始化 2 { 3 if(dis[s][node[i].id]+node[i].ci<=t) 4 { 5 dp[node[i].id][node[i].ci+dis[s][node[i].id]]=node[i].si; 6 } 7 //if(t-dis[s][node[i].id]-node[i].ci>=dis[node[i].id][e]) 8 // ans=max(ans,node[i].si); 9 }
我注释的 这两行是可以省去的 <如果我没理解错的话>
然后 接下去 就是一个很重要的 3层遍历了
因为我们在初始化之前就已经sort好了 让城市是按照满意程度从小到大排序的 所以我们肯定是从1 - n递推的
然后 注意时间是要 递减的 这就和01背包中 体积逆序遍历一个道理 物品<景点>只能取一次
//////////////////////////////////
总的来说 这题 很好!!!!!
today:
think and think
believe youselft
just jj =_=