2020年浙江理工大学新生赛 E DD_BOND买赛博朋克2077
注意:本文还处于 EA 阶段,亟待修正和完善
最后一次更新时间:2021/11/10 20:55
注意:本文的代码可以AC,但解释可能有误,思路仅供参考
动态规划+线段树
参考:
https://blog.csdn.net/qq_39641976/article/details/111195335
https://blog.csdn.net/zearot/article/details/52280189
https://blog.csdn.net/zearot/article/details/48299459
《赛博朋克 2077》 购买链接(大雾) https://store.steampowered.com/app/1091500/_2077/
题目描述
今天,看了赛博朋克2077试完后的DD_BOND,决定买它买它买它!!看了看它的价格要298后,DD_BOND看了眼自己的余额,想想有没有便宜的方法可以购买。正巧,当DD_BOND打开steam后,他发现G胖正在搞促销,只需要集齐298298个不同的点数后,就可以兑换赛博朋克2077啦。
那么现在商店中一共有m
个礼包,第i
个礼包需要花费v[i]
的价格,礼包中包含l[i]~r[i]
的所有点数,DD_BOND比较笨蛋,想寻求你帮助他,告诉他最少需要花费多少价格可以集齐1
到298298
的所有点数,如果不可以,请告诉他-1
。
输入
一个整数m
(1<=m<=1e5
),表示有m
个礼包,接下来m
行,每行有l[i],r[i],v[i]
(1<=l[i]<=r[i]<=298298
,0<=v[i]<=1e9
)表示该礼包包含的点数和该礼包价格。
输出
若不能集齐1~298298
所有点数输出-1
,否则输出最小总价格。
样例输入
【样例1输入】
3
1 2077 1
2078 298298 2
2 298298 3
【样例2输入】
3
1 2077 1
2078 298297 3
2 21233 5
样例输出
【样例1输出】
3
【样例2输出】
-1
题目分析:
一、题意概括(来自参考链接1)
给出n
个区间,每段区间有三个值l,r,v
,v
表示花费v
的代价可以覆盖区间[l,r]
,求覆盖区间[1,298298]
的最小代价
二、用动态规划解题(关于DP部分,后文有不使用线段树的等价代码)
(1) 定义dp[]
的含义
dp[i]
定义为拥有前i
个点的最小花费
那么dp[298298]
为本题答案(由于使用线段树,实际上dp[298298+1]
才是答案,代码注释会提及)
(2) 找出dp[]
间的关系式(该部分亟待完善,可以先凑合看看2333)
首先对各个区间按右端点升序排序,右端点相同的情况按左端点升序排序
然后从前往后开始遍历每一个区间,对于当前区间l,r,v
来说,我们可以从dp[j]
(l-1<=j<=r)
转移到当前dp[k]
(l<=k<=r)
,可以得出状态转移方程
dp[r]=min(dp[r],dp[l-1 -> r]+v)
其中
dp[l-1 -> r] <=> dp[i],i∈[l-1,r]
(3) 找出初始条件
由于要找最小花费,规定dp[]
初始值为较大数INF
在这里 INF=0x3f3f3f3f3f3f3f3f
如果当前区间的l=1
,那么l-1=0
,为了让状态转移方程给dp[1]
赋上值,需要规定dp[0]=0
(这里的数组下标在代码中被右移一位,实际上dp[1]=0
)
三、用线段树模拟数组dp[]
详见代码,该部分日后完善
AC 代码如下
代码来源于以上三个参考链接,我根据自己的理解补充全文注释,如有谬误可及时指出
原代码应用了 快速读入
和 结构体内嵌比较函数
,以提升程序运行速度。为简化代码,我使用了更简单暴力的方法(cin
和sort()
的cmp()
参数)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define Inf 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 3e5+5;
struct node{//结构体存每个区间 int l,r;long long val;
}nod[maxn];bool cmp(node x,node y){//对结构体sort()所需函数 if(x.r==y.r) return x.l<y.l;else return x.r<y.r;//对各个区间按右端点升序排序,右端点相同按左端点升序排序
}/*--------------------------*/
/*-----以下为线段树部分-----*/
/*--------------------------*/ ll n,a[maxn<<2];//数组存储线段树,开4倍空间
//x*2 等价于 x<<1
//x*4 等价于 x<<2
//x*2+1 等价于 x<<1|1 void pushup(int root){//更新节点信息,这里是求左右子节点的最小值 a[root]=min(a[root<<1],a[root<<1|1]);//root*2是左下方节点,root*2+1是右下方节点
}void build(int root,int l,int r){//建树//root为当前节点在a[]的对应下标,即实际存储位置 //[l,r]表示当前节点区间 if(l==r){//到达叶子节点 a[root]=Inf;//初始化节点值为Inf,用于比最小值,同时参与判断是否所有 Steam 点数都被覆盖 return ;}int mid=l+r>>1;//左右递归,等价于min=(l+r)/2 build(root<<1 ,l ,mid);build(root<<1|1,mid+1,r );pushup(root);//递归完,更新本节点信息
}
void update(int root,int l,int r,int pos,ll val){//点修改 //root,l,r含义同上//pos为线段树所表达的数组dp的实际下标 pos∈[1,298298+1] //value是想要修改成的值 if(l==r){//到达叶子节点 a[root]=min(a[root],val);//修改为最小值 return ;}int mid=l+r>>1;//判断需要向左走还是向右走,从上往下一路走到叶子节点 if(pos<=mid) update(root<<1,l,mid,pos,val);else update(root<<1|1,mid+1,r,pos,val);//递归(走)完更新本节点信息 pushup(root);
}
ll query(int root,int l,int r,int ql,int qr){//区间查询 if(l>qr || r<ql) return Inf;//查询范围超出[ql,qr],且没有交叉部分.同时参与判断是否所有 Steam 点数都被覆盖 else if(l>=ql && r<=qr) return a[root];//在区间内直接返回值 else{//有交叉部分,递归到交叉部分,返回交叉部分的值 int mid=l+r>>1;return min(query(root<<1,l,mid,ql,qr),query(root<<1|1,mid+1,r,ql,qr));}
}
int main(){cin>>n;for(int i=0;i<n;i++){cin>>nod[i].l>>nod[i].r>>nod[i].val;nod[i].l++;nod[i].r++;//由于线段树习惯从1开始建立,而nod[i].l-1在l=1时等于0,所以把所有区间向右移1位 }sort(nod,nod+n,cmp);/*以下为线段树部分*/ //线段树模拟数组dp[1 -> 298298+1] build(1,1,maxn);//建树update(1,1,maxn,1,0);//线段树所模拟的dp[1]赋初值为0 /*---下面这个for循环,后文有可参考的等价代码---*/ for(int i=0;i<n;i++){ll minn=query(1,1,maxn,nod[i].l-1,nod[i].r);//查询dp[l-1 -> r]最小值 minn+=nod[i].val;//最小值加上新值 update(1,1,maxn,nod[i].r,minn);}/*------------------------------------------*/ll ans=query(1,1,maxn,298298+1,298298+1);//查询线段树所模拟的数组dp[298298+1] if(ans!=Inf) cout<<ans;else cout<<-1;return 0;
}
可供参考的等价代码
时间超限 AC40%
这段代码没有用线段树模拟数组dp[]
,直接暴力在dp[]
数组进行区间查询和修改。理论上功能是相同的,可帮助理解DP
部分
注意:没有充分的测试数据表明两段代码是等价的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define Inf 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 3e5+5;
struct node{int l,r;long long val;
}nod[maxn];bool cmp(node x,node y){if(x.r==y.r) return x.l<y.l;else return x.r<y.r;
}ll n,dp[maxn];
int main(){cin>>n;for(int i=0;i<n;i++)cin>>nod[i].l>>nod[i].r>>nod[i].val;sort(nod,nod+n,cmp);for(int i=1;i<=maxn;i++)dp[i]=Inf;for(int i=0;i<n;i++){ll minn=Inf;for(int j=nod[i].l-1;j<=nod[i].r;j++)minn=min(minn,dp[j]);minn+=nod[i].val;for(int j=nod[i].l;j<=nod[i].r;j++)dp[j]=min(minn,dp[j]);}ll ans=dp[298298];if(ans<Inf) cout<<ans; else cout<<-1<<endl;return 0;
}
2020年浙江理工大学新生赛 E DD_BOND买赛博朋克2077相关推荐
- 2020年浙江理工大学新生赛 D DD_BOND看到的hcy
签到题 Description 一般来说,从这个角度来看,问题的关键究竟为何?这样看来,我认为,一般来说, 要想清楚,hcy到底是一种怎么样的存在.经过上述讨论,经过上述讨论,带着这些问题,我们来审视 ...
- 2020年浙江理工大学新生赛 B Cly的博弈
注意:本文的代码可以AC,但解释可能有误,思路仅供参考 Description Cly很喜欢博弈,这天他和他的分身DD_BOND玩起了一个博弈游戏(本体当然是先手了),游戏规则如下,请你判断谁能赢得游 ...
- 2020年浙江理工大学新生赛 C Cly的三角形
Description Cly很喜欢三角形,有一天他遇到了一道和三角形有关的题,但是这道题他简单了,他懒得做,于是交给了你. 给定一个数组,每次询问一个子区间,如果能从这个子区间挑出三个数组成三角形输 ...
- 2021浙江理工大学新生赛被毒打记录
Problem A: nudun故事集之ATM出的线段树 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 367 Solved: 16 Descrip ...
- 2021年浙江理工大学新生赛同步赛
Problem K: nudun故事集之约会 Description 题目背景 时隔多年,赚了不少达不溜的zmw想要来一场甜甜的恋爱,于是乎他找到了万能的nudun.在情场高手mk23ez66的介绍下 ...
- 2017哈尔滨理工大学新生赛
A: 仔细读题ORZ A.涂山红十字会 Time Limit: 1000 MS Memory Limit: 256000 K Total Submit: 1121 (338 users) Total ...
- 2020年浙江理工大学计算机考研经验分享
首先,作为一名二本高校的学生,通常在考试准备中或多或少的存在一些自卑感,不敢大胆选择自己心仪的学校,因为毕竟考试只是一部分,后面还有面试选导师等各种乱七八糟的一系列事情等着你们(往往这些环节刷掉了一部 ...
- [SUCTF2018]babyre [ACTF新生赛2020]fungame
文章目录 [SUCTF2018]babyre 惯用思维 常人思维 GAMEOVER [ACTF新生赛2020]fungame int __cdecl sub_401340(int a1) int __ ...
- BUU [ACTF新生赛2020]Universe_final_answer
[ACTF新生赛2020]Universe_final_answer 首先查壳, 64bit 无壳 ida64位打开 main() __int64 __fastcall main(int a1, ch ...
最新文章
- java从Object类型转换成double类型
- python颜色的字母代码,如何在python中更改特定印刷字母的颜色?
- CSS之media Query
- eclipse加速之禁用JS、jsp等文件的语法验证
- 坚果Pro 3发布,罗永浩大赞科大讯飞:不成器国产厂商尽早跟讯飞合作
- java项目中用了Disruptor之后,性能提升了10倍
- (转) Dockerfile 中的 COPY 与 ADD 命令 1
- 交换机的VLAN与Trunk配置
- idea 2020 社区版传递参数
- Landsat 数据下载与预处理
- 基础回顾:10W+ 字 C 语言入门教程(上)
- M1芯片的Mac在开发iOS项目时遇到的问题汇总(模拟器无法运行,Cocoapods错误等)
- matlab向量乘法要加.,matlab中的矩阵与向量运算
- Java实现消息队列服务
- 微信小程序赞赏功能,非微信赞赏功能
- 有空必须要看的文章(没空也要看)
- 远程办公和分布式协作
- 中国好生意 经典论述:哈林是来主持的,刘欢是来开家长会的,那英是来唠嗑的,杨坤是来做宣传的,而......
- ps水花飞溅效果制作
- 常用数据集预处理(dota)
热门文章
- html给图片添加id,如何在Indesign批量导入图片?ID中单次导入多张图片(分页放置)的方法...
- Kali Linux之ARP欺骗和DNS劫持
- 【阴沟翻船】AVPlayer设置完毕马上调用play方法会导致播放没声音
- D. For Gamers. By Gamers.
- VDA 6.3 难点之“过程划分”
- 基于 Yara 引擎的二进制文件扫描
- 2019考研上岸经验
- CC2640R2F学习笔记(九.总结)
- ifconfig命令结果详解
- PYNQ例程一:1.3 PYNQ Overlays