蓝桥杯C++大学B组一个月冲刺记录2024/2/28
规则:每日三题
今日感冒了。
1.冶炼金属
小蓝有一个神奇的炉子用于将普通金属 O 冶炼成为一种特殊金属 X。
这个炉子有一个称作转换率的属性 V,V是一个正整数,这意味着消耗 V 个普通金属 O恰好可以冶炼出一个特殊金属 X,当普通金属 O 的数目不足 V时,无法继续冶炼。
现在给出了 N 条冶炼记录,每条记录中包含两个整数 A 和 B,这表示本次投入了 A个普通金属 ,最终冶炼出了 B个特殊金属 X。
每条记录都是独立的,这意味着上一次没消耗完的普通金属 O不会累加到下一次的冶炼当中。
根据这 N 条冶炼记录,请你推测出转换率 V的最小值和最大值分别可能是多少,题目保证评测数据不存在无解的情况。
第十四届蓝桥杯真题,我觉得给的数据有点怪,但AC了就无所谓了
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int M = 1e9;
int N = -1;
int main(){
int n;
cin >> n;
while(n--){
int T,p;
cin >> T >> p;
M = min(M,T/p);
N = max(N,T/(p+1) + 1);
}
cout << N << ' ' << M;
return 0;
}
2.机器人跳跃问题
机器人正在玩一个古老的基于 DOS 的游戏。游戏中有 N+1座建筑——从 0到 N
编号,从左到右排列。编号为 0的建筑高度为 0个单位,编号为 i的建筑高度为 H(i)个单位。
起初,机器人在编号为 0 的建筑处。每一步,它跳到下一个(右边)建筑。
假设机器人在第 k个建筑,且它现在的能量值是 E,下一步它将跳到第 k+1个建筑。
如果 H(k+1)>E,那么机器人就失去 H(k+1)−E的能量值,否则它将得到 E−H(k+1) 的能量值。
游戏目标是到达第 N个建筑,在这个过程中能量值不能为负数个单位。
现在的问题是机器人至少以多少能量值开始游戏,才可以保证成功完成游戏?
发现答案是单调递增的,二分答案去寻找即可
1.对于初始化条件,r=高度最大值,l可以是第一座建筑的高度的1/2。但是由于整数和分数还需要单独处理,所以设定l = 0
2.当能量超过建筑高度最大值,一定符合题意,可以直接return true
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int r = -1;
int l = 0;
int f;
const int MAx = 1e5+10;
int res[MAx];
int n;
bool check(int e){
for(int i = 1;i <= n;++i){
e = 2*e - res[i];
if(e >= f) return true;
if(e < 0) return false;
}
return true;
}
int main(){
cin >> n;
for(int i = 1;i <= n; ++i){
cin >> res[i];
r = max(r,res[i]);
}
f = r;
while(l < r){
int mid = (l+r)/2;
if(check(mid) == false) l = mid + 1;
else r = mid;
}
cout << l << endl;
return 0;
}
3.飞机降落
有 N 架飞机准备降落到某个只有一条跑道的机场。
其中第 i架飞机在 Ti时刻到达机场上空,到达时它的剩余油料还可以继续盘旋 Di个单位时间,即它最早可以于 Ti时刻开始降落,最晚可以于 Ti+Di时刻开始降落。降落过程需要 Li个单位时间。
一架飞机降落完毕时,另一架飞机可以立即在同一时刻开始降落,但是不能在前一架飞机完成降落前开始降落。
请你判断 N 架飞机是否可以全部安全降落。
本人菜逼,以为这个题就是贪心模拟,结果只过了60%的数据。
贪心想法是按照最迟降落时间排个序,靠前的肯定更急,所以先降落。但是是错误的
可能存在情况是两个飞机可能最迟降落时间一致,但是由于到的时间不一样,以及降落时间不一样,存在先后关系
正确做法:dfs爆搜
(以下是我贪心的做法,写的挺顺,记录一下)
#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct Node{
int T,D,L;
int lt;
};
bool cmp(Node a, Node b){
return a.lt < b.lt;
}
vector<Node>q;
vector<Node>::iterator it;
int n,m;
bool check(){
int rt;
for(int i = 0;i < q.size(); ++ i){
if(i == 0){
rt = q[0].T + q[0].L;
}
else{
if(rt > q[i].lt) return false;
else{
rt = rt + q[i].L;
}
}
}
return true;
}
int main(){
cin >> n;
while(n--){
int m;
cin >> m;
while(m--){
Node k;
cin >> k.T >> k.D >> k.L;
k.lt = k.T + k.D;
q.push_back(k);
}
sort(q.begin(),q.end(),cmp);
if(check()) cout << "YES" << endl;
else cout << "NO" << endl;
q.clear();
}
return 0;
}
正确的dfs做法(以前写的)
#include<iostream>
#include<cstring>
using namespace std;
const int N = 1e5+10;
int ar[N],wa[N],l[N],n;
bool f[N];
bool flag = false;
void dfs(int u,int x,int t){
if(u > n){
flag = true;
return;
}
f[x] = true;
for(int i = 1;i <= n;++i){
if(f[i] == false&&ar[i] + wa[i] >= t){
f[i] = true;
dfs(u+1,i,max(t,ar[i])+l[i]);
f[i] = false;
}
}
}
int main(){
int k;
cin >> k;
while(k--){
memset(f,0,sizeof(f));
flag = false;
cin >> n;
for(int i = 1;i <= n; ++i){
cin >> ar[i] >> wa[i] >> l[i];
}
dfs(1,0,0);
if(flag) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
4.刷题统计
注意数据范围
#include<iostream>
#include<cstdio>
using namespace std;
long long int a,b,n;
int main(){
cin >> a >> b >> n;
long long int res = 0;
long long int tot = 0;
long long int days = 0;
long long int week = a*5 + b*2;
days += n/week * 7;
n = n%week;
if(n == 0){
cout << days << endl;
return 0;
}
else{
while(true){
res += 1;
days ++;
if(res >= 1 && res <= 5){
tot += a;
}
else{
tot += b;
}
if(tot >= n) break;
if(res == 7) res = 0;
}
cout << days << endl;
}
return 0;
}
5.修建灌木
找规律题,注意单数和双数分开处理
#include<iostream>
#include<cstdio>
using namespace std;
const int MAx = 1e5+10;
int f[MAx];
int N;
int main(){
cin >> N;
if(N % 2 == 0){
int mid = N /2;
for(int i = 1;i <= mid;++i){
int j = N - i;
f[i] = 2*j;
cout << f[i] << '\n';
}
for(int i = mid;i >= 1;--i){
cout << f[i] << '\n';
}
}
else{
int mid = N / 2 + 1;
for(int i = 1;i <= mid;++i){
int j = N - i;
f[i] = 2*j;
cout << f[i] << '\n';
}
for(int i = mid - 1;i >= 1;--i){
cout << f[i] << '\n';
}
}
return 0;
}