• Codeforces1249E By Elevator or Stairs?


    题意

    给定整数c和数组a,b,(a_i)表示通过爬楼梯的方法从第(i)层到(i+1)层需要的时间,(b_i)表示通过坐电梯的方法从第(i)层到(i+1)层需要的时间,坐电梯前需要等c单位时间。即对于(i<j),通过爬楼梯的方法要从第(i)层到第(j)层,需要(sum_i^{j-1}a_i)的时间,而坐电梯需要(c+sum_i^{j-1}b_i)的时间。

    解题思路

    很明显的dp题,首先考虑最简单的dp思路,对于每次层枚举他是从之前的那一层转移过来的,即

    [dp_j=min left{ dp_i + sum_i^{j-1}a_i,dp_i+c+sum_i^{j-1}b_i ight} ]

    这样dp的复杂度是(O(n^2)),显然会TLE,所以考虑优化一下
    使用前缀和的方法后式子变为

    [dp_j=min left{ dp_i + sa_{j-1}-sa_i,dp_i+c+sb_{j-1}-sb_i ight} ]

    对于(j),可以将式子中的(sa_{j-1})(sb_{j-1})视为常数,那么式子变为

    [dp_j=min left{ minleft{dp_i - sa_i ight} + sa_{j-1},min left{dp_i - sb_i ight}+c+sb_{j-1} ight} ]

    记录(dp_i - sa_i)(dp_i - sb_i)的最小值,每次更新即可,复杂度(O(n))

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int maxn=2e5+5;
    
    int n,c,a[maxn],b[maxn];
    ll dp[maxn];
    
    int main()
    {
    	scanf("%d %d",&n,&c);
    	for(int i=1;i<=n-1;i++)scanf("%d",&a[i]),a[i]+=a[i-1];
    	for(int i=1;i<=n-1;i++)scanf("%d",&b[i]),b[i]+=b[i-1];
    	ll A=0,B=0;
    	printf("%lld",dp[1]);
    	for(int i=1;i<=n-1;i++){
    		dp[i]=min(B+b[i]+c,A+a[i]);
    		
    		A=min(A,dp[i]-a[i]);
    		B=min(B,dp[i]-b[i]);
    		
    		printf(" %lld",dp[i]);
    	}
        return 0;
    }
    
  • 相关阅读:
    调试跳转动态打印
    PHP对redis操作详解
    SSL证书没有绿锁您与此网站建立的连接并非完全安全解决办法
    63. Unique Paths II
    62. Unique Paths
    40. Combination Sum II
    60. Permutation Sequence
    59. Spiral Matrix II
    批量修改名字的脚本
    57. Insert Interval
  • 原文地址:https://www.cnblogs.com/zengzk/p/11725731.html
Copyright © 2020-2023  润新知