• 【做题笔记】P1359租用游艇


    不知为啥我觉得这是一道挺毒瘤的dp,,,可能是我太弱了。


    那个半矩阵一开始我都不知道是啥。。。

    感谢@do_while_true 以及 @qym2008 的回答:https://www.luogu.com.cn/discuss/show/207793

    拿样例来说:

    3
    5 15
    7
    

    5为1行1数,表示1到2距离;
    15为1行2数,表示1到3距离;
    (i) 行第 (j) 个数表示 (i) 到点 (j+1) 的距离,不妨记为 (x)

    然后这题之所以可以不用最短路算法做是因为,题目直接给出了整个图的信息,而我们又只需要求1~n的“最短路”。 所以我们设计一种 dp 算法即可。

    注意到我们只关心最后的结果是多少,而不关心中间到底经过了哪些路线,所以记 (f_j) 为 1~j 的最小花费,那么有:

    [f_j=min{f_j,f_i+x} ]

    为什么能这么干呢?我们发现,1~j 的路径有很多条,假设我们现在有一条 1~i 的目前的最短路径,而现在又输入了 (x) 代表 i~j 的花费,那么最优解必定有可能被更新,因为 (f_i) 代表目前的 1~i 的最优花费,那么加上刚刚输入的那一条边,就有可能产生一条新的路径,使得花费更优。例如下图:

    G9mbCV.png

    紫色的路径是我们以前找到的,那么假如又知道了左边的那条路径((f_i+x)),最优值就被更新了!见下图绿色线路:

    G9nZbd.png

    但是该题的初始值不太好弄。有一个解决办法就是因为每次给的数据一定为非负数,所以没有经过的点对应的 (f) 值必定为0。遇到这种情况直接更新路径就好。

    参考代码:

    #include <cstdio>
    #include <algorithm>
    
    int f[2020], n, x;
    
    int main(void) {
    	scanf("%d", &n);
    	
    	for(int i=1;i<n;i++) {
    		for(int j=i+1;j<=n;j++) {
    			scanf("%d", &x);
    			if(f[j] == 0) f[j]=f[i]+x;
                //直接更新路径
    			else f[j] = std::min(f[j], f[i]+x);
                //否则比较,选择更优的方案
    		}
    	}
    	
    	printf("%d
    ", f[n]);
    	return 0;
    }
    
  • 相关阅读:
    在Windows平台上安装Node.js及NPM模块管理
    MySQL远程访问授权
    JSON (仅限本地)
    Json 调用 天气API 实例
    JS调用腾讯接口获取天气
    jsonp 调用天气API
    兼容性
    MySql like模糊查询使用详解
    编绎报错,解决方法objc_msgSend too many arguments to function call,expected 0, have3 (转)
    OC中ARC forbids explicit message send of release错误(转)
  • 原文地址:https://www.cnblogs.com/BlueInRed/p/12617576.html
Copyright © 2020-2023  润新知