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

Input
The first line of the input contains two integers nn and cc (2≤n≤2⋅105,1≤c≤10002≤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 n−1n−1 integers a1,a2,…,an−1a1,a2,…,an−1 (1≤ai≤10001≤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 n−1n−1 integers b1,b2,…,bn−1b1,b2,…,bn−1 (1≤bi≤10001≤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
10 2
7 6 18 6 16 18 1 17 17
6 9 3 10 9 1 10 1 5
0 7 13 18 24 35 36 37 40 45
10 1
3 2 3 1 3 3 1 4 1
1 2 3 4 4 1 2 1 3
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[][][]=c;//电梯来电梯走,需要等电梯
dp[][][]=c;//电梯来楼梯走,需要等电梯
dp[][][]=;//楼梯来电梯走
dp[][][]=;//楼梯来楼梯走
之后不管是走楼梯还是乘电梯都需要加上楼梯到楼梯或者电梯到电梯转的时间。如果碰到楼梯转电梯的情况,加上c即可。
动态转移方程如下:
dp[i][][]=min(dp[i-][][]+b[i-],dp[i-][][]+b[i-]+c);
dp[i][][]=min(dp[i-][][]+b[i-],dp[i-][][]+b[i-]+c);
dp[i][][]=min(dp[i-][][]+a[i-],dp[i-][][]+a[i-]);
dp[i][][]=min(dp[i-][][]+a[i-],dp[i-][][]+a[i-]);
三维代码:
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int N=2e5+; int a[N],b[N];
int dp[N][][]; //dp[i][j][k] 到达第几层,j来,k走
//0电梯 1楼梯
int main()
{
int n,c;
while(~scanf("%d %d",&n,&c))
{
memset(dp,,sizeof(dp));
// for(int i=2;i<=n;i++)//0 7 13 18 24 35 36 37 40 45
// wa 0 0 7 13 18 24 35 36 37 40
for(int i=; i<n; i++)
scanf("%d",&a[i]);//楼梯1
for(int i=; i<n; i++)
scanf("%d",&b[i]);//电梯0
dp[][][]=c;//电梯来电梯走,需要等电梯
dp[][][]=c;//电梯来楼梯走,需要等电梯
dp[][][]=;//楼梯来电梯走
dp[][][]=;//楼梯来楼梯走
for(int i=; i<=n; i++)
{
dp[i][][]=min(dp[i-][][]+b[i-],dp[i-][][]+b[i-]+c);
dp[i][][]=min(dp[i-][][]+b[i-],dp[i-][][]+b[i-]+c);
dp[i][][]=min(dp[i-][][]+a[i-],dp[i-][][]+a[i-]);
dp[i][][]=min(dp[i-][][]+a[i-],dp[i-][][]+a[i-]);
}
printf("0 ");
for(int i=;i<=n;i++)
{
if(i!=)
printf(" ");
int w=min(dp[i][][],dp[i][][]);
int ww=min(w,dp[i][][]);
int www=min(ww,dp[i][][]);
printf("%d",www);
}
printf("\n");
}
return ;
}
优化后的二维代码:
经过三维数组观察可得:
dp[i][][]=dp[i][][]=min(dp[i-][][]+b[i-],dp[i-][][]+b[i-]+c);
dp[i][][]=dp[i][][]=min(dp[i-][][]+a[i-],dp[i-][][]+a[i-]);
所以与从哪来有关,与到哪去无关
从而可以写成二维数组
代码如下:
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int N=2e5+; int a[N],b[N],dp[N][]; //dp[i][j][k] 到达第几层,j来,k走
//0电梯 1楼梯 int main()
{
int n,c;
while(~scanf("%d %d",&n,&c))
{
memset(dp,,sizeof(dp));
for(int i=; i<n; i++)
scanf("%d",&a[i]);//楼梯1
for(int i=; i<n; i++)
scanf("%d",&b[i]);//电梯0
dp[][]=c;
dp[][]=;
for(int i=; i<=n; i++)
{
dp[i][]=min(dp[i-][]+b[i-],dp[i-][]+b[i-]+c);
dp[i][]=min(dp[i-][]+a[i-],dp[i-][][]+a[i-]);
}
printf("0 ");
for(int i=;i<=n;i++)
{
if(i!=)
printf(" ");
int w=min(dp[i][],dp[i][]);
printf("%d",w);
}
printf("\n");
}
return ;
}
CodeForces1249E-By Elevator or Stairs?-好理解自己想不出来的dp的更多相关文章
- Codeforces1249E By Elevator or Stairs?
题意 给定整数c和数组a,b,\(a_i\)表示通过爬楼梯的方法从第\(i\)层到\(i+1\)层需要的时间,\(b_i\)表示通过坐电梯的方法从第\(i\)层到\(i+1\)层需要的时间,坐电梯前需 ...
- [题解]Mail.Ru Cup 2018 Round 1 - A. Elevator or Stairs?
[题目] A. Elevator or Stairs? [描述] Masha要从第x层楼去第y层楼找Egor,可以选择爬楼梯或者坐直升电梯.已知爬楼梯每层需要时间t1:坐直升电梯每层需要时间t2,直升 ...
- Codeforces 1249 E. By Elevator or Stairs?
传送门 首先显然下楼的操作一定是不优的,所以只要考虑上楼 设 $f[i]$ 表示到第 $i$ 层时需要的最少时间 那么首先考虑走楼梯,有转移,$f[i]=f[i-1]+a[i-1]$ 然后考虑坐电梯有 ...
- Codeforces 1249E By Elevator or Stairs? 题解
这题其实和 NIKKEI 2019-2-D Shortest Path on a Line 差不多的啦,都是一种最短路的变形,把多个点和边关联了起来. 题面 你要从一楼到 \(n\) 楼去,每层楼可以 ...
- javascript中继承(二)-----借用构造函数继承的个人理解
本人目录如下: 零.寒暄&回顾 一,借用构造函数 二.事件代理 三,call和apply的用法 四.总结 零.寒暄&回顾 上次博客跟大家分享了自己对原型链继承的理解,想看的同学欢迎猛击 ...
- 一步一步深入理解Dijkstra算法
先简单介绍一下最短路径: 最短路径是啥?就是一个带边值的图中从某一个顶点到另外一个顶点的最短路径. 官方定义:对于内网图而言,最短路径是指两顶点之间经过的边上权值之和最小的路径. 并且我们称路径上的第 ...
- Java的内部类真的那么难以理解?
01 前言 昨天晚上,我把车停好以后就回家了.回家后才发现手机落在车里面了,但外面太冷,冷到骨头都能感受到寒意——实在是不想返回一趟去取了(小区的安保还不错,不用担心被砸车玻璃),于是打定主意过几个小 ...
- 转发对python装饰器的理解
[Python] 对 Python 装饰器的理解的一些心得分享出来给大家参考 原文 http://blog.csdn.net/sxw3718401/article/details/3951958 ...
- http://python.jobbole.com/85056/ 简单 12 步理解 Python 装饰器,https://www.cnblogs.com/deeper/p/7482958.html另一篇文章
好吧,我标题党了.作为 Python 教师,我发现理解装饰器是学生们从接触后就一直纠结的问题.那是因为装饰器确实难以理解!想弄明白装饰器,需要理解一些函数式编程概念,并且要对Python中函数定义和函 ...
随机推荐
- spring boot starter开发
作为公司的技术保障部,一直承担着技术方向的把控,最近公司准备全面转入spring boot的开发.所以我们部门也一直在调研相关的技术知识点: 使用springboot开发应用已经有一段时间了,我们都沉 ...
- NetworkComms V3 序列化器之Protobuf.net和 JSONSerializer
NetworkComms v3版本中,默认使用的是protobuf.net序列化器. 即当您没有指定序列化的时候,系统自动使用默认的protobuf.net序列化器. 当然我们也可以自己指定序列化器 ...
- numpy的函数使用
目录 注 help ,帮助 numpy.genfromtxt,导入文件 array,创建数组(1,2维数组) array,创建行列向量 numpy.shape,看numpy数据的行列信息 numpy. ...
- JVM内存图
- java 并发——synchronized
java 并发--synchronized 介绍 在平常我们开发的过程中可能会遇到线程安全性的问题,为了保证线程之间操作数据的正确性,我们第一想到的可能就是使用 synchronized 并且 syn ...
- spring data jpa 关联设计
MAP关联实体 // @ElementCollection @OneToMany(cascade = {CascadeType.ALL})// @JoinColumn(name = "the ...
- Java面试必问-ThreadLocal
前言 在面试环节中,考察"ThreadLocal"也是面试官的家常便饭,所以对它理解透彻,是非常有必要的. 有些面试官会开门见山的提问: “知道ThreadLocal吗?” “讲讲 ...
- C# winform 文件管理
1.FolderBrowserDialog 打开文件夹中默认路径下的excl文件 private void button7_Click(object sender, EventArgs e) { Fo ...
- mysql架构精选
◆主从架构1.安装服务(主从) yum -y install mysql* /etc/init.d/mysqld start2.修改配置文件:/etc/my.conf(主从) vi /etc/my.c ...
- 微服务-熔断器 Hystrix 的原理与使用
前言 分布式系统中经常会出现某个基础服务不可用造成整个系统不可用的情况, 这种现象被称为服务雪崩效应. 为了应对服务雪崩, 一种常见的做法是手动服务降级. 而Hystrix的出现,给我们提供了另一种选 ...