By Elevator or Stairs? CodeForces - 1249E(动态规划)

题意

n层楼,a[i] (0<i<n)表示从 i 楼到 i + 1 楼走楼梯的时间,b[i] (0<i<n)表示从 i 楼到 i + 1 楼乘电梯的时间,其中每一次乘电梯需要等待 k 时间,楼梯和电梯一次均可上从 x 楼上升到 y 楼 ( y != x ),即一次可以通过楼梯或电梯上升任意层数 。求从1楼到 1 ~ n 层楼所需要的最短时间

题目

You are planning to buy an apartment in a nn-floor building. The floors are numbered from 1 to n from the bottom to the top. At first for each floor you want to know the minimum total time to reach it from the first (the bottom) floor.

Let:

aiai for all ii from 1 to n−1 be the time required to go from the ii-th floor to the (i+1)-th one (and from the (i+1)-th to the i-th as well) using the stairs;
bibi for all ii from 11 to n−1n−1 be the time required to go from the ii-th floor to the (i+1)-th one (and from the(i+1)-th to the ii-th as well) using the elevator, also there is a value c — time overhead for elevator usage (you need to wait for it, the elevator doors are too slow!).
In one move, you can go from the floor you are staying at xx to any floor yy (x≠y) in two different ways:

If you are using the stairs, just sum up the corresponding values of aiai. Formally, it will take ∑ m i n ( x , y ) m a x ( x , y ) − 1 a i \sum_{min(x,y)}^{max(x,y)−1}ai min(x,y)max(x,y)1ai time units.
If you are using the elevator, just sum up cc and the corresponding values of bibi. Formally, it will take c+ ∑ m i n ( x , y ) m a x ( x , y ) − 1 b i \sum_{min(x,y)}^{max(x,y)−1}bi min(x,y)max(x,y)1bi time units.
You can perform as many moves as you want (possibly zero).

ai

So your task is for each ii to determine the minimum total time it takes to reach the ii-th floor from the 1-st (bottom) floor.

Input

The first line of the input contains two integers n and c (2≤n≤2⋅ 1 0 5 10^{5} 105,1≤c≤1000) — the number of floors in the building and the time overhead for the elevator rides.

The second line of the input contains n−1 integers a1,a2,…,an−1 (1≤ai≤1000), where aiai is the time required to go from the ii-th floor to the (i+1)-th one (and from the(i+1)-th to the ii-th as well) using the stairs.

The third line of the input contains n−1n−1 integers b1,b2,…,bn−1 (1≤bi≤1000), where bibi is the time required to go from the ii-th floor to the (i+1)-th one (and from the (i+1)-th to the ii-th as well) using the elevator.

Output

Print nn integers t1,t2,…,tn where titi is the minimum total time to reach the ii-th floor from the first floor if you can perform as many moves as you want.

Examples

Input

10 2
7 6 18 6 16 18 1 17 17
6 9 3 10 9 1 10 1 5

Output

0 7 13 18 24 35 36 37 40 45

Input

10 1
3 2 3 1 3 3 1 4 1
1 2 3 4 4 1 2 1 3

Output

0 2 4 7 8 11 13 14 16 17

官方题解

This is easy dynamic programming problem. It is easy to understand that we don’t need to go down at all (otherwise your solution will be Dijkstra’s algorithm, not dynamic programming). Let dpi,0be the minimum required time to reach the floor ii if we not in the elevator right now and dpi,1 be the minimum required time to reach the floor ii if we in the elevator right now.

Initially, all values dp are +∞, except dp1,0=0 and dp1,1=c.

Transitions are pretty easy:

dpi+1,0=min(dpi+1,0,dpi,0+ai) (we was not in the elevator and going to the next floor using stairs);
dpi+1,0=min(dpi+1,0,dpi,1+ai) (we was in the elevator and going to the next floor using stairs);
dpi+1,1=min(dpi+1,1,dpi,0+bi+c) (we was not in the elevator and going to the next floor using elevator);
dpi+1,1=min(dpi+1,1,dpi,1+bi) (we was in the elevator and going to the next floor using elevator).
The answer for the ii-th floor is min(dpi,0,dpi,1).

Time complexity: O(n).

百度翻译

这是一个简单的动态规划问题。很容易理解,我们根本不需要往下走(否则你的解决方案将是Dijkstra的算法,而不是动态编程)如果我们现在不在电梯里,dpi,0是到达二层的最小要求时间;如果我们现在在电梯里,dpi,1是到达二层的最小要求时间。
最初,除dp1,0=0和dp1,1=c外,所有值dp均为+∞。
转换非常容易:
dpi+1,0=min(dpi+1,0,dpi,0+ai)(我们当时不在电梯里,正在下一层楼梯上);
dpi+1,0=min(dpi+1,0,dpi,1+ai)(我们当时在电梯里,正在下一层楼梯上);
dpi+1,1=min(dpi+1,1,dpi,0+bi+c)(我们不在电梯里,乘电梯去下一层);
dpi+1,1=min(dpi+1,1,dpi,1+bi)(我们在电梯里,乘电梯去了下一层)。
第二层的答案是min(dpi,0,dpi,1)。
时间复杂度:O(n)。

思路

dp题:二维数组dp[i][j],表示通过 j 的方法( j = 0 表示楼梯,j = 1表示电梯)第 i 层所需的最少时间。
可以看出有四种状态,
楼梯——》楼梯
楼梯——》电梯
电梯——》电梯
电梯——》楼梯
所以得出状态转移方程
dp[i+1][0]=min(dp[i][1]+a[i],dp[i][0]+a[i]);
dp[i+1][1]=min(dp[i][1]+b[i],dp[i][0]+b[i]+c);
简单是真简单(理解题意,推出转移方程),难是真的难(总会想偏,或是没有思路)菜的抠脚​​​​​​

AC代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2*1e5+10;
const int inf=0x3f3f3f3f;
int a[N],b[N],dp[N][2];
int n,c;
int main()
{
    while(~scanf("%d%d",&n,&c))
    {
        for(int i=1; i<n; i++)
            scanf("%d",&a[i]);
        for(int i=1; i<n; i++)
            scanf("%d",&b[i]);
        memset(dp,inf,sizeof(dp));
        dp[1][0]=0,dp[1][1]=c; ///dp[i][0]:走楼梯到达第i层,dp[i][1]:做电梯到达第i层
        for(int i=1; i<n; i++)
        {
            dp[i+1][0]=min(dp[i][1]+a[i],dp[i][0]+a[i]);
            dp[i+1][1]=min(dp[i][1]+b[i],dp[i][0]+b[i]+c);
        }
        for(int i=1; i<=n; i++)
            printf("%d ",min(dp[i][0],dp[i][1]));
        printf("\n");
    }
    return 0;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值