今天这一期是来还债的,都是之前跳过的几个比较难的题目,大多是思路上走不太通或者走得通但落实不出来的,感谢提供思路的朋友~
有难度的一期,废话不多说,先上题目为敬~
1🐋🐋🐋MC0219自驾游(钻石;动态规划)
时间限制:10秒
占用内存:256M
🐟题目描述
小码哥最近刚考完驾照,又恰逢暑假将到,便决定自驾游一番,一来可以欣赏大美新疆,二来还能磨炼驾驶技术。
小码哥查阅各种旅游资料后,挑选了几个旅游胜地,以及几条风景不错的公路,并规划出总行程 L 的路线。由于新疆太大了,小码哥必须要在沿途多次加油才能跑完全程,在他规划的这条路线上共计 N个加油站,可以直接加满。第 ii 个加油站位于 Pi,想要在这里加满需要花费 Ci块钱,一个位置上可能有多个加油站。
小码哥的车油量上限为 Maxn,初始的时候视为油量满额,每消耗一单位油,可以跑一单位行程。当油量见底的时候,车就会抛锚(如果当前位置有加油站,他仍然可以加油)。小码哥预算可拿出 S 块钱用于加油,他想知道自己能否完成这次自驾游。
🐟输入输出格式
输入格式: 本题包含多组数据,每组数据包含N+1N+1行: 第一行输入四个正整数N,L,Maxn,S; 接下来NN行,每行输入两个正整数Pi,Ci,其中Pi不一定是顺序给出的。 输出格式: 每组数据输出一行,如果小码哥能够完成自驾游,那么输出”Yes”,否则输出”No”。
🐟样例
🐚样例1
输入: 1 1000 500 2000 500 2000 1 1000 500 2000 500 3000 输出: Yes No
🐚备注
其中:0≤N≤2000, 0≤L≤20000, 0≤Maxn≤20000, 0≤S≤2000;1≤Pi≤N, 1≤Ci≤3000
🐟题目思路
这道题,官方提示是BFS(广度优先遍历),但是我不太会,所以学习的评论区的思路,使用动态规划。
🐟代码
#include<bits/stdc++.h>
using namespace std;
bool cmp(pair<int,int> a,pair<int,int> b)//自定义的比较大小的函数,用于sort中规定排序方式
{
return a.first<b.first;
}
int main( )
{
int N,L,MAX,S,flag=0;
while(cin>>N>>L>>MAX>>S)//※用于判断后方是否还有字符
{
//flag=0;
map<int,int> m;
m[0]=0;//0是出发点
int a,b;//(优化思想)这是一个优化点,如果定义放在for循环中,那么会申请N次内存,这样只用申请1次
for(int i=0;i<N;i++)
{
cin>>a>>b;
m[a]=b;//map可以直接赋值,位于a的加油站需要花b元
}
//加油站信息放到数组里排序,模拟真实加油的情况
vector<pair<int,int> > data(m.begin(),m.end());
sort(data.begin(),data.end(),cmp);//按加油站位置进行排序,这就是模拟路上到加油站的情况
int dp[2010]={0};//动态规划数组,记录到当前位置最少需要花多少钱
for(int i=1;i<=N;i++)//0是出发点,所以从第1个加油站开始判断
{
dp[i]=INT_MAX;//※用于直接设置为无穷大
for(int j=0;j<i;j++)//遍历当前所在加油站前方的所有加油站,用于接下来的判断
{
//1:判断能否到达
if(data[j].first+MAX<data[i].first) continue;//前边的任意一个加油站都不足以让小码哥到当前加油站所在位置,排除这个加油站
//第j个加油站可以让小码哥到当前位置的加油站
//2:判断还有没有钱
dp[i]=min(dp[i],dp[j]+data[j].second);//※※※动态规划更新函数※※※
//如果不加油,到当前位置的花费就是dp[i],加油就是后边那项
if(dp[i]+data[i].second<=S&&data[i].first+MAX>=L) //如果此时,花的钱少于等于小码哥有的钱,并且剩下的油足以到达重点了,那么就可以输出yes结束了
{
cout<<"Yes"<<endl;
//flag=1;
//break;
goto flag;
}
}
//if(flag==1) break;
}
//if(flag==0) cout<<"No"<<endl;
cout<<"No"<<endl; //所有情况都不能输出yes,说明没法满足,输出no
flag: //用于跳转的空语句,goto flag后会直接到当前位置,跳过NO的输出
;
}
return 0;
}
代码思路来自题目评论区——小码_112662
-
我刚开始用flag做标记来判断是否输出no和何时结束,但是第3个数据点一直过不了,有没有懂的大佬们帮忙看看解答一下~ 谢谢🌹~
-
还有一个地方就是goto flag那里,我对goto语句比较陌生,有时候flag: ;可以执行过第3个数据点,有时候过不了,有没有懂的大佬们帮忙解答下~ 谢谢🌹~
2🐋🐋🐋MC0221未来战争(黄金)
时间限制:4秒
占用内存:256M
🐟题目描述
公元 2099 年,小码哥和小码弟所在的两个国家陷入战争。小码哥所在的城市需要用激光武器来防守,而激光武器需要定时充能。小码哥和他的战友们每天都要凌晨 4 点起床,然后去为守城的激光武器充能。
我们可以把每个人为激光武器充能的时间段看作一段区间 [l, r](以秒为单位,从凌晨 4 点开始计时),其中 l 表示充能的开始时刻,r 表示充能的结束时刻。例如,如果一个人在 300 秒的时候开始充能,直到 1000 秒的时候结束,我们可以表示为区间 [300, 1000]。
现在,我们有一个列表,其中包含了 n 个人为 n 个激光武器充能的时间段,我们想要计算以下两个问题: 1.最长的至少有一个人在为激光武器充能的连续时间段是多长? 2.最长的没有人为激光武器充能的连续时间段是多长?
假设有 3 个人,他们的充能时间段分别为 [300, 1000],[700, 1200] 和 [1500, 2100]。则最长的至少有一个人在为激光武器充能的连续时间段为 900 秒(从 300 秒到 1200 秒),最长的没有人为激光武器充能的连续时间段为 300 秒(从 1200 秒到 1500 秒)。
🐟输入输出格式
输入格式: 输入第一行为一个正整数 n; 接下来输入 n 行,每行两个非负整数 l,r,表示一个人充能的开始时刻与结束时刻。整数之间以空格间隔。 输出格式: 输出一行,两个整数,表示最长至少有一人在充能的时间段和最长的无人充能的时间段。整数之间以空格间隔。 如果从第一个人开始充能,到最后一个人充能结束,都不存在无人充能的时间段,那么对于第二个问题应该输出0。
🐟样例
🐚样例1
输入: 3 300 1000 700 1200 1500 2100 输出: 900 300
🐚备注
其中:1≤n≤5×10^3,0≤l≤r≤10^6。 关于连续区间的判断:若充能区间为[1,2],[2,6],则在[1,6]时间区间内都视为在充能;若充能区间为[1,2],[3,5],则在[2,3]区间内无人充能。
🐟题目思路
这道题目官网给的思路是前缀和,但是我不太会,所有参考了评论区的思路,类似双指针,也类似模拟。具体步骤就是:
-
两个二维数组a和b,分布记录所有区间信息和每个最长的连续区间段
-
数组a进行排序便于顺序遍历所有的区间左右端点
-
数组b的更新方式:如果当前区间的左端点还在b的最后一个区间范围内,那么就直接更新b中最后一个区间的右端点为二者的最大值即可;否则,b中插入新区间
-
ans1记录最长连续充能区间,就是最长的b中区间
-
ans2记录最长间断区间,那就是两个b中区间的最长(后一个区间的)前端点减(前一个区间的)后端点
🐟代码
#include<bits/stdc++.h>
using namespace std;
int main( )
{
int n;
cin>>n;
int l,r;
vector<vector<int> > a,b;//※动态二维数组;a用来记录区间数据,b用来记录每个(最长化处理后的)连续区间
for(int i=0;i<n;i++)//插入区间
{
cin>>l>>r;
a.push_back({l,r}); //※第i个位置的数组将被插入两个数
}
sort(a.begin(),a.end());//排序,为了顺序遍历所有区间的左右端点
int ans1=0,ans2=0,ll,rr;//ans1是最长的充能区间,ans2是最长的非充能时间
for(int i=0;i<a.size();i++)//遍历所有区间
{
//得到每个区间的左、右时间
ll=a[i][0];
rr=a[i][1];
if(!b.size()||b.back()[1]<ll) b.push_back({ll,rr});//如果数组b为空或者b的最后一个区间的右端点比当前区间的左端点小:插入新区间
else b.back()[1]=max(b.back()[1],rr);//其他情况(开始的区间还在当前区间内):b的最后一个区间的右端更新为最远的那个
ans1=max(ans1,b.back()[1]-b.back()[0]);
}
for(int i=1;i<b.size();i++) ans2=max(ans2,b[i][0]-b[i-1][1]);
cout<<ans1<<" "<<ans2<<endl;
return 0;
}
代码思路来自题目评论区——DTS小花
欢迎大家提供更多样、高效的代码,如果后续知道上述的问题的原因了,我也会在评论区更新的,我们评论区见~
⭐点赞收藏不迷路~