CodeForces1249E-By Elevator or Stairs?-好理解自己想不出来的dp

随声附和 提交于 2019-12-02 19:25:12

 

Input

The first line of the input contains two integers nn and cc (2n2105,1c10002≤n≤2⋅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 n1n−1 integers a1,a2,,an1a1,a2,…,an−1 (1ai10001≤ai≤1000), where aiai is the time required to go from the ii-th floor to the (i+1)(i+1)-th one (and from the (i+1)(i+1)-th to the ii-th as well) using the stairs.

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

Output

Print nn integers t1,t2,,tnt1,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 题意:给出n、c,表示有n层楼,等电梯需要c时间;给出两行数,每行有n-1个数,第一行stairs代表从1楼到每层楼走楼梯需要的时间第二行elevator代表从1楼到每层楼乘电梯需要的时间;需要注意的是,从电梯转电梯不需要等待时间,从楼梯转楼梯也不需要等待时间,但是从楼梯转电梯需要算上等待的时间 t 。求:从1楼到每层楼所需的最短时间,输出应该有n-1个时间。思路:由于存在两种状态,所以可以用0代表乘电梯,1代表走楼梯;所以一开始可以按照题目所给的开一个三维数组dp [ i ] [ j ] [ k ],i代表乘电梯还是走楼梯,j代表当前到达第几层,k代表将要去第几层。所以一开始进行dp清空接下来赋初值,由于不知道从1楼往上走是等电梯还是走楼梯,所以假设等电梯的话需要赋初值dp=c,算上等电梯的时间。初始化如下:
memset(dp,0,sizeof(dp));
dp[1][0][0]=c;//电梯来电梯走,需要等电梯
dp[1][0][1]=c;//电梯来楼梯走,需要等电梯
dp[1][1][0]=0;//楼梯来电梯走
dp[1][1][1]=0;//楼梯来楼梯走
之后不管是走楼梯还是乘电梯都需要加上楼梯到楼梯或者电梯到电梯转的时间。如果碰到楼梯转电梯的情况,加上c即可。动态转移方程如下:
dp[i][0][1]=min(dp[i-1][0][0]+b[i-1],dp[i-1][1][0]+b[i-1]+c);
dp[i][0][0]=min(dp[i-1][0][0]+b[i-1],dp[i-1][1][0]+b[i-1]+c);
dp[i][1][0]=min(dp[i-1][0][1]+a[i-1],dp[i-1][1][1]+a[i-1]);
dp[i][1][1]=min(dp[i-1][0][1]+a[i-1],dp[i-1][1][1]+a[i-1]);


 三维代码:

 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<string.h>
 4 using namespace std;
 5 const int N=2e5+20;
 6 
 7 int a[N],b[N];
 8 int dp[N][2][2];
 9 
10 //dp[i][j][k] 到达第几层,j来,k走
11 //0电梯 1楼梯
12 int main()
13 {
14     int n,c;
15     while(~scanf("%d %d",&n,&c))
16     {
17         memset(dp,0,sizeof(dp));
18 //        for(int i=2;i<=n;i++)//0 7 13 18 24 35 36 37 40 45 
19 //        wa 0 0 7 13 18 24 35 36 37 40 
20         for(int i=1; i<n; i++)
21             scanf("%d",&a[i]);//楼梯1
22         for(int i=1; i<n; i++)
23             scanf("%d",&b[i]);//电梯0
24         dp[1][0][0]=c;//电梯来电梯走,需要等电梯
25         dp[1][0][1]=c;//电梯来楼梯走,需要等电梯
26         dp[1][1][0]=0;//楼梯来电梯走
27         dp[1][1][1]=0;//楼梯来楼梯走
28         for(int i=2; i<=n; i++)
29         {
30             dp[i][0][1]=min(dp[i-1][0][0]+b[i-1],dp[i-1][1][0]+b[i-1]+c);
31             dp[i][0][0]=min(dp[i-1][0][0]+b[i-1],dp[i-1][1][0]+b[i-1]+c);
32             dp[i][1][0]=min(dp[i-1][0][1]+a[i-1],dp[i-1][1][1]+a[i-1]);
33             dp[i][1][1]=min(dp[i-1][0][1]+a[i-1],dp[i-1][1][1]+a[i-1]);
34         }
35         printf("0 ");
36         for(int i=2;i<=n;i++)
37         {
38             if(i!=2)
39                 printf(" ");
40             int w=min(dp[i][0][1],dp[i][0][0]);
41             int ww=min(w,dp[i][1][0]);
42             int www=min(ww,dp[i][1][1]);
43             printf("%d",www);
44         }
45         printf("\n");
46     }
47     return 0;
48 }

 

优化后的二维代码:

经过三维数组观察可得:

dp[i][0][1]=dp[i][0][0]=min(dp[i-1][0][0]+b[i-1],dp[i-1][1][0]+b[i-1]+c);
dp[i][1][0]=dp[i][1][1]=min(dp[i-1][0][1]+a[i-1],dp[i-1][1][1]+a[i-1]);

所以与从哪来有关,与到哪去无关
从而可以写成二维数组

 

代码如下:

 

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int N=2e5+20;

int a[N],b[N],dp[N][2];

//dp[i][j][k] 到达第几层,j来,k走
//0电梯 1楼梯

int main()
{
    int n,c;
    while(~scanf("%d %d",&n,&c))
    {
        memset(dp,0,sizeof(dp));
        for(int i=1; i<n; i++)
            scanf("%d",&a[i]);//楼梯1
        for(int i=1; i<n; i++)
            scanf("%d",&b[i]);//电梯0
        dp[1][0]=c;
        dp[1][1]=0;
        for(int i=2; i<=n; i++)
        {
            dp[i][0]=min(dp[i-1][0]+b[i-1],dp[i-1][1]+b[i-1]+c);
            dp[i][1]=min(dp[i-1][0]+a[i-1],dp[i-1][1][1]+a[i-1]);
        }
        printf("0 ");
        for(int i=2;i<=n;i++)
        {
            if(i!=2)
                printf(" ");
            int w=min(dp[i][0],dp[i][1]);
            printf("%d",w);
        }
        printf("\n");
    }
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!