程设2021期末题F:交易市场

原题:http://cxsjsx.openjudge.cn/2021finalpractise/F/

描述

市场里面一共有n种物品,有m种交易途径,每个交易途径可以由(x,y,z)表示,意思是可以用第x种物品换成第y种物品,并且得到z元的收益(z均大于0)。最开始你只有第一种物品,请问最多可以赚取多少收益。

输入

第一行两个正整数n和m(n ≤ 1000,m ≤ 4000)
接下来m行,每行三个正整数x, y, z,意思是可以用第x种物品换成第y种物品,并且得到z元的收益。(1 ≤ x,y ≤ n, 1 ≤ z ≤ 100)

输出

一个整数表示最大收益,如果可以赚取无穷多的收益则输出1000000000

样例输入

3 3
1 2 2
2 3 3
1 3 4

样例输出

5 

解法

这道题用动态规划可以做。采用我为人人型递推。

dp[i]表示最后是第i种物品时的最大价值,无穷多的收益等于出现环,要判断环所以要记录路径。扫描到每个转换关系时更新目标节点的dp。

注意这道题还有广搜的思想,动态规划的节点顺序是用队列来决定,有的节点根本到不了就不用考虑它的转换关系。有的节点增加了转换关系就应该重新计算。

代码如下:

 1 #include <iostream>
 2 #include <vector>
 3 #include <map>
 4 #include <set>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <queue>
 8 #define INF 1000000000
 9 using namespace std;
10 struct exchangeTo {
11     int target;
12     int p;
13     exchangeTo(int a, int b) :target(a), p(b) {}
14 };
15 struct path {
16     int pre;
17     int val;
18 }dp[1005];
19 map<int, vector<exchangeTo> >tables;
20 bool inPath(int n, int k) {
21     while (k != -1) {
22         if (n == k)
23             return true;
24         k = dp[k].pre;
25     }
26     return false;
27 }
28 int main() {
29     memset(dp, -1, sizeof(dp));
30     int n, m;
31     cin >> n >> m;
32     for (int i = 0; i < m; i++) {
33         int x, y, z;
34         cin >> x >> y >> z;
35         tables[x].push_back(exchangeTo(y, z));
36     }
37     dp[1].val = 0, dp[1].pre = 0;
38     bool done = false;
39     int result = 0;
40     queue<int>myqueues;
41     myqueues.push(1);
42     while (!myqueues.empty()) {
43         int top = myqueues.front();
44         myqueues.pop();
45         if (!tables[top].empty()) {
46             vector<exchangeTo>::iterator ii;
47             for (ii = tables[top].begin(); ii != tables[top].end(); ii++) {
48                 if (inPath(ii->target, top))
49                 {
50                     result = INF;
51                     done = true;
52                     break;
53                 }
54                 if (dp[top].val + ii->p > dp[ii->target].val) {
55                     dp[ii->target].val = dp[top].val + ii->p;
56                     dp[ii->target].pre = top;
57                     myqueues.push(ii->target);//注意这里的更新
58                 }
59                 result = max(result, dp[ii->target].val);
60             }
61             if (done)break;
62         }
63     }
64     cout << result << endl;
65     return 0;
66 }

 

posted @ 2021-07-19 21:26  永远是个小孩子  阅读(790)  评论(0)    收藏  举报