2023第十四届蓝桥杯C++B组题目回顾与参赛感想
更新一下结果: 省三,惊喜的同时又有点感伤。惊喜是本以为参与奖了,感伤是没做好,时间没分配好,本不该如此的...
时隔几天,终于还是忍不住来复盘一下蓝桥杯了,还记得去年参加做下填空,再做对个把编程,后面不会的大题打打表混混分,最后就能混个省奖,
这回估计凉透了,填空没对似乎,编程也没对几个,混分也没来得及混甚至题目都没来的及看,这次只能说复盘一下做了的几个题目,可能是错误的,希望有大佬能指出来纠正一下思路;
1、试题A:日期统计
解题思路与代码
暴力枚举的,我咋是365咧?上山打老虎大佬说是235;
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
using namespace std;
/*
5 6 8 6 9 1 6 1 2 4
9 1 9 8 2 3 6 4 7 7
5 9 5 0 3 8 7 5 8 1
5 8 6 1 8 3 0 3 7 9
2 7 0 5 8 8 5 7 0 9
9 1 9 4 4 6 8 6 3 3
8 5 1 6 3 4 6 7 0 7
8 2 7 6 8 9 5 6 5 6
1 4 0 1 0 0 9 4 8 0
9 1 2 8 5 0 2 5 3 3
5 6 8 6 9 1 6 1 4
9 1 9 8 2 3 6 4 7 7
5 9 5 0 3 8 7 5 8 1
5 8 6 1 8 3 0 3 7 9
2 7 0 5 8 8 5 7 9
9 1 9 4 4 6 8 6 3 3
8 5 1 6 3 4 6 7 0 7
8 2 7 6 8 9 5 6 5 6
1 4 0 1 0 0 9 4 8 0
9 1 2 8 5 0 5 3
*/
string mm[]={"01","02","03","04","05","06","07","08","09","10","11","12"};
string dd[]={"01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31"};
int months[]={31,28,31,30,31,30,31,31,30,31,30,31};
int a[96];//2023固定找出来不要了,少写代码省事儿;
bool isExist(string str){
bool pos[96];//记录访问过的位置 ,如果这个数字被取过就标记它不能再取了
for(int i = 0; i < 96; i++) pos[i] = true;
int flag = 0;
for(int j = 0; j < 4; j++){
int c = str[j]-'0';
for(int i = 0; i < 96; i++){
if(( c == a[i]) && (pos[i] == true)) {
flag++;
pos[i] = false;
break;
}
}
}
return flag == 4;
}
int main(){
long long ans = 0;
for(int i = 0; i < 96; i++) cin>>a[i];
for(int i = 0; i < 12; i++){
for(int j = 0; j < months[i]; j++){
string tmp = mm[i] + dd[j];
if(isExist(tmp)) ans++;
}
}
cout<<ans<<endl;
return 0;
}
2、试题B:01串的熵
解题思路与代码
长度为23333333的01字符串,
log2( 0的出现次数 / 总长度 ) * 一个相应的值 的总数和
log2( 1的出现次数 / 总长度 ) * 一个相应的值 的总数和
两者相加为信息熵的值;由于0出现的次数比1少,所以直接二分找0出现次数的边界值就行;
结果为 11027421
#include<bits/stdc++.h>
using namespace std;
#define ll long long
double p(ll x,ll y){ //x 0 y 1
double P0 = 1.0*x/(x+y);
double P1 = 1.0*y/(x+y);
return -1.0*x*x/(x+y)*log2(P0)-1.0*y*y/(x+y)*log2(P1);
};
int main(){
ll n = 23333333;
ll l=1, r=(n-1)/2;
double PP = 11625907.5798;
while(l<r){
int mid = (l+r)>>1;
double t = p(mid, n-mid);
if(t<PP) l=mid+1;
else r=mid;
}
cout << l << endl;
return 0;
}
3、试题C:冶炼金属
解题思路与代码
A / V = B
求V的最大值和最小值
V 最小时 V = A / (B + 1) 代入多列数据求最大值
V 最大时 V = A / B 代入多列数据求最小值
#include <bits/stdc++.h>
using namespace std;
int main(){
int n; cin>>n;
int a[n][2];
for(int i = 0; i < n; i++){
cin>>a[i][0]>>a[i][1];
}
int maxv = 1e7, minv = 0, tmp = 0;
for(int i = 0; i < n; i++){
tmp = a[i][0] / a[i][1];
maxv = min(maxv, tmp);
tmp = a[i][0] / (a[i][1] + 1);
minv = max(minv, tmp);
}
cout<< minv + 1 << " " << maxv <<endl;
return 0;
}
4、试题D:飞机降落
解题思路与代码
贪心算法之区间调度问题 : https://zhuanlan.zhihu.com/p/91254104
看到这个区间问题,第一时间想起的是贪心,然后纠结了这个区间尾很久(因为有个该死的盘旋时间啦,CPU干烧了),最终还是用的T+D的时间作为排序依据,所幸样例能过,不知是否正确,尽力了;该死的题目纠结了好久好久浪费了太多时间
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
using namespace std;
typedef struct airplane{
int t;//到达的时间
int d;//盘旋的时间
int l;//降落的时间
}ap;
int main(){
int t; cin>>t;//t,测试的组数
while(t--){//计算t组次
int n; cin>>n;//n组数据
if(n == 1) return true;
ap a[n];
for(int i = 0; i < n; i++){
cin>>a[i].t>>a[i].d>>a[i].l;//获取这组数据
}
sort(a, a+n, [](ap m, ap n){
return m.t+m.d < n.t+n.d;//谁最不能持久,谁就先降
});
// for(int i = 0; i < n; i++) cout<<a[i].t<<" "<<a[i].d<<" "<<a[i].l<<endl;//调试数据
bool ans = true;
int ap_end = a[0].t + a[0].l;//第一架飞机停好的时间
for (int i = 1; i < n; i++) {
int ap_start = a[i].t + a[i].d;//下一架飞机最晚开始的时间
if (ap_end > ap_start) {
ans = false;
break;
}
if(a[i].t > ap_end){//要么上架飞机停好了我到了开始停,要么就是我盘旋到了ap_end上一架飞机停好了开始停;
ap_end = a[i].t + a[i].l;
} else ap_end += a[i].l;
}
if(ans) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
5、试题E:接龙数列
解题思路与代码
6、试题H:整数删除
解题思路与代码
这个题可能是最轻松的一个题,只考了stl的使用,当发现我没时间做后面的题以后,浏览了一下,挑了它先做了;
用一个multimap存位置关系,并且可以把元素从小到大排序,按顺序取最小值和最小值的位置,并将该位置的左右两边的非0的值加上最小值,然后把该位置置0,表示该元素被删除了,最后遍历输出时不要输出0就行;
#include <bits/stdc++.h>
using namespace std;
int main(){
int n, k; cin>>n>>k;
multimap<int, int> mp; // 记录位置关系 key值, value 位置,同时自动根据key值排序就能知道最小值
vector<int> pos(n + 1, 0);// 记录元素左右两边的值
for(int i = 1; i <= n; i++){
cin>>pos[i];
mp.insert(pair<int, int>(pos[i], i));
}
auto it = mp.begin();
for(int i = 1; i <= k; i++){
int e = it->second, eleft = it->second - 1, eright = it->second + 1;
while(pos[eleft] == 0) eleft--;
if(eleft >= 1) pos[eleft] += pos[e];
while(pos[eright] == 0) eright++;
if(eright <= n) pos[eright] += pos[e];
pos[e] = 0;
it++;
}
for(int i = 1; i <= n; i++){
if(pos[i] != 0) cout<< pos[i] << " ";
}
return 0;
}
后记
后面又挑了相对简单的一题做还没做完就结束了,到这里就结束了,菜鸡的落幕,感慨很多,不必要的地方浪费了很多时间导致后面的题目都没来的做,这里复盘的时候,基本上思路都是比赛的思路,但是代码又是重新敲的,发现整数删除哪里每次如果直接删除的话所有的元素都要位移很麻烦,所以采用了置0的方法;日期统计竞赛也是那么做的但是肯定错了,还不知道怎么错了,求指点;飞机降落不知正误,也是尽力了;光荣捐躯300元,真它喵的谢谢你啊;这把多半寄了,See You Again
更多推荐
所有评论(0)