注意:本文还处于 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比较笨蛋,想寻求你帮助他,告诉他最少需要花费多少价格可以集齐1298298的所有点数,如果不可以,请告诉他-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,vv表示花费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 代码如下

代码来源于以上三个参考链接,我根据自己的理解补充全文注释,如有谬误可及时指出

原代码应用了 快速读入结构体内嵌比较函数,以提升程序运行速度。为简化代码,我使用了更简单暴力的方法(cinsort()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相关推荐

  1. 2020年浙江理工大学新生赛 D DD_BOND看到的hcy

    签到题 Description 一般来说,从这个角度来看,问题的关键究竟为何?这样看来,我认为,一般来说, 要想清楚,hcy到底是一种怎么样的存在.经过上述讨论,经过上述讨论,带着这些问题,我们来审视 ...

  2. 2020年浙江理工大学新生赛 B Cly的博弈

    注意:本文的代码可以AC,但解释可能有误,思路仅供参考 Description Cly很喜欢博弈,这天他和他的分身DD_BOND玩起了一个博弈游戏(本体当然是先手了),游戏规则如下,请你判断谁能赢得游 ...

  3. 2020年浙江理工大学新生赛 C Cly的三角形

    Description Cly很喜欢三角形,有一天他遇到了一道和三角形有关的题,但是这道题他简单了,他懒得做,于是交给了你. 给定一个数组,每次询问一个子区间,如果能从这个子区间挑出三个数组成三角形输 ...

  4. 2021浙江理工大学新生赛被毒打记录

    Problem A: nudun故事集之ATM出的线段树 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 367  Solved: 16 Descrip ...

  5. 2021年浙江理工大学新生赛同步赛

    Problem K: nudun故事集之约会 Description 题目背景 时隔多年,赚了不少达不溜的zmw想要来一场甜甜的恋爱,于是乎他找到了万能的nudun.在情场高手mk23ez66的介绍下 ...

  6. 2017哈尔滨理工大学新生赛

    A: 仔细读题ORZ A.涂山红十字会 Time Limit: 1000 MS Memory Limit: 256000 K Total Submit: 1121 (338 users) Total ...

  7. 2020年浙江理工大学计算机考研经验分享

    首先,作为一名二本高校的学生,通常在考试准备中或多或少的存在一些自卑感,不敢大胆选择自己心仪的学校,因为毕竟考试只是一部分,后面还有面试选导师等各种乱七八糟的一系列事情等着你们(往往这些环节刷掉了一部 ...

  8. [SUCTF2018]babyre [ACTF新生赛2020]fungame

    文章目录 [SUCTF2018]babyre 惯用思维 常人思维 GAMEOVER [ACTF新生赛2020]fungame int __cdecl sub_401340(int a1) int __ ...

  9. BUU [ACTF新生赛2020]Universe_final_answer

    [ACTF新生赛2020]Universe_final_answer 首先查壳, 64bit 无壳 ida64位打开 main() __int64 __fastcall main(int a1, ch ...

最新文章

  1. java从Object类型转换成double类型
  2. python颜色的字母代码,如何在python中更改特定印刷字母的颜色?
  3. CSS之media Query
  4. eclipse加速之禁用JS、jsp等文件的语法验证
  5. 坚果Pro 3发布,罗永浩大赞科大讯飞:不成器国产厂商尽早跟讯飞合作
  6. java项目中用了Disruptor之后,性能提升了10倍
  7. (转) Dockerfile 中的 COPY 与 ADD 命令 1
  8. 交换机的VLAN与Trunk配置
  9. idea 2020 社区版传递参数
  10. Landsat 数据下载与预处理
  11. 基础回顾:10W+ 字 C 语言入门教程(上)
  12. M1芯片的Mac在开发iOS项目时遇到的问题汇总(模拟器无法运行,Cocoapods错误等)
  13. matlab向量乘法要加.,matlab中的矩阵与向量运算
  14. Java实现消息队列服务
  15. 微信小程序赞赏功能,非微信赞赏功能
  16. 有空必须要看的文章(没空也要看)
  17. 远程办公和分布式协作
  18. 中国好生意 经典论述:哈林是来主持的,刘欢是来开家长会的,那英是来唠嗑的,杨坤是来做宣传的,而......
  19. ps水花飞溅效果制作
  20. 常用数据集预处理(dota)

热门文章

  1. html给图片添加id,如何在Indesign批量导入图片?ID中单次导入多张图片(分页放置)的方法...
  2. Kali Linux之ARP欺骗和DNS劫持
  3. 【阴沟翻船】AVPlayer设置完毕马上调用play方法会导致播放没声音
  4. D. For Gamers. By Gamers.
  5. VDA 6.3 难点之“过程划分”
  6. 基于 Yara 引擎的二进制文件扫描
  7. 2019考研上岸经验
  8. CC2640R2F学习笔记(九.总结)
  9. ifconfig命令结果详解
  10. PYNQ例程一:1.3 PYNQ Overlays