洛谷 P1073 最优贸易

    科技2024-01-25  106

    1.分析

    这道题目做法有很多,作为一个初学者,还是用深搜来解答。上课老师提示过有两个剪枝条件

    最小价格没有改变则退出最大利润没有改变则退出

    所以在写深搜的时候,需要记录一下最小价格和最大利润。

    洛谷的题解第一名采取了深搜加动态规划的方式,他的DP思路和我们老师上课提示过的很相似。只不过他的代码中,记录最大利润的数组、记录最小价格的数组都可以被优化掉 ,虽然算法题不需要考虑空间复杂度。

    2.AC代码

    #include <iostream> #include <algorithm> #include <stdlib.h> #include <cstring> #include <stdio.h> #include<vector> using namespace std; #define MAX 1000000 int n,m; vector<int> g[100001]; int profit[100001];// 到 第i个城市时的最大利润 int Price[100001]; int minPri; void dfs(int now,int pre,int min_price) { int flag=1; // min_price=min(min_price,Price[now]); if(min_price>Price[now]) { flag=0; min_price=Price[now]; } int a=max(profit[pre],Price[now]-min_price); if(a>profit[now]) { flag=0; profit[now]=a; } if(flag) return; for (int i = 0; i < g[now].size(); i++) { dfs(g[now][i],now,min_price); } } int main() { int a; int i; int x,y; scanf("%d %d",&n,&m); for ( i = 1; i <= n; i++) { scanf("%d",&Price[i]); } for ( i = 1; i <= m; i++) { scanf("%d %d %d",&x,&y,&a); g[x].push_back(y); if(a==2) { g[y].push_back(x); } } dfs(1,0,MAX); cout<<profit[n]<<endl; }

    我这里的代码并没有优化掉记录最大值的数组。如果保留了这个最大值的数组,就更有动态规划的感觉了。

    3.反思

    这道题目关键是如何剪枝/DP。

    因为售出价格可能在将来出现,所以我们总是希望购入价格尽可能地小。所以当最小价格没有更好的改进的时候,这个点就没有那么好了。其次,如果购入价格没有变的更低的话,我们需要考虑利润了。如果利润更好,说明这个点是有进一步深搜的价值的。感觉像是以是否在当前城市卖出为分界。 如果在当前城市卖出,那么说明在当前城市所获得的利润,比之前的利润都要高。可以记录一下当前城市所获得的利润,然后继续向下深搜,看有没有更好的利润。如果不在当前城市卖出,说明最低价格更新了,我们可以向下面的城市看看有无更高的价格让我们出售。
    Processed: 0.011, SQL: 9