第十四届蓝桥杯c/c++B组 赛后复盘wa

 复盘反思:

  今天打完蓝桥杯,感觉自己被雷到了,简单题做不出,复杂题也只会暴力。感觉两个月的备赛就是场笑话,全程没有优美的算法可言,只有一层层堆砌的暴力循环。经过这场比赛,我明白了自己极其不扎实的技术功底以及缺乏参加大赛的经历。我在备战蓝桥杯的前期是使用acwing的,天天手抄y总代码以为自己有多牛b,最后到头来样样学不精。今年的自己确实令我失望,不过咱也不能气馁。从哪里跌倒,就要从哪里爬起来。趁着现在才大一,好好的沉淀一年,不要追求快速!不要自以为是!不要浮躁。明年,我还来捐300.不过那时候,我一定会拿回属于我的荣誉!!!

题目复盘

 试题A:日期统计

 【考试状态】:

  看到第一题名字的时候还以为又是什么签到题,毕竟以往几年的蓝桥杯的日期题我从来没有卡过。可是因为第一次参加比赛,我紧张得不得了,题都没读明白,后来明白了题意,判断的时候又总是不能完全不重不漏,写了半个小时的各种循环判断,最后还是选择手算。提交的答案是327,错大离谱了。

【题意分析】:

  其实,题目的思想本身不难,但是模拟很是复杂。而且现在其实我还是没有搞懂条件1

和条件2不是有冲突吗?子序列要为8,可是条件2又变相的告诉我子序列不一定为8,遇到单日期只需要补上前导0就行??????我就是这里好迷糊。算了,继续来分析。我们可以分单月单日期、单月双日期、双月单日期、双月双日期四个方式来做到不重不漏。然后借助dfs的来找到我们的答案。

这是考试时我的思路

 利用dfs算法思想 (学长给的代码,还没吃透hh)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
set<string> st;
int mon[13] = { 31, 30, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int a[110];


//s是日期,id是100位数组编号,u是枚举到第几位,v是s的每一位
void dfs(string s, int id, int u, char v)  
 {
	if (u == 9) {
		st.insert(s);
		//		cout << s << "\n";
		return;
	}
	if (id > 100) return;
	if (u == 1) {
		if (a[id] == 2) {
			dfs(s + '2', id + 1, u + 1, 2);
		}
	}
	else if (u == 2) {
		if (a[id] == 0) {
			dfs(s + '0', id + 1, u + 1, 0);
		}
	}
	else if (u == 3) {
		if (a[id] == 2) {
			dfs(s + '2', id + 1, u + 1, 2);
		}
	}
	else if (u == 4) {
		if (a[id] == 3) {
			dfs(s + '3', id + 1, u + 1, 3);
		}
	}
	else if (u == 5) {
		if (a[id] <= 1) {
			char c = '0' + a[id];
			dfs(s + c, id + 1, u + 1, a[id]);
		}
	}
	else if (u == 6) {
		if (v == 0 && a[id] == 0) {

		}
		else if (v == 0 && a[id] > 0) {
			char c = '0' + a[id];
			dfs(s + c, id + 1, u + 1, a[id]);
		}
		else if (v == 1 && a[id] <= 2) {
			char c = '0' + a[id];
			dfs(s + c, id + 1, u + 1, a[id]);
		}
	}
	else if (u == 7) {
		if (a[id] <= 3) {
			char c = '0' + a[id];
			dfs(s + c, id + 1, u + 1, a[id]);
		}
	}
	else if (u == 8) {
		if (v == 3) {
			int num = (s[4] - '0') * 10 + s[5] - '0';
			if (mon[num] == 31 && a[id] <= 1) {
				char c = '0' + a[id];
				dfs(s + c, id + 1, u + 1, a[id]);
			}
		}
		else if (v == 0 && a[id] == 0) {

		}
		else {
			char c = '0' + a[id];
			dfs(s + c, id + 1, u + 1, a[id]);
		}
	}

	char c = '0' + a[id];
	dfs(s, id + 1, u, v);
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	for (int i = 1; i <= 100; ++i) {
		cin >> a[i];
	}
	dfs("", 1, 1, 0);
	cout << st.size() << "\n";
	return 0;
}

 【复盘代码】

#include<bits/stdc++.h>
using namespace std;
int a[100],ans;
bool vis[20240000];
bool check(int date){           //判断日期合法性
	if(vis[date]) return false;
	vis[date]=true;
	int mm=date/100%100;
	int dd=date%100;
	if(mm<1||mm>12)return false;
	if(mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12){
		if(dd>=1&&dd<=31) return true;
	}else if(mm==2){
		if(dd>=1&&dd<=28)return true;
	}else if(dd>=1&&dd<=30)return true;
	else return  false;
} 

void dfs(int x,int pos,int date){    //x是当前枚举的下标,pos是当前枚举的位数,date是当前组成的日期 
	if(x==100)return ;
	if(pos==8){
		if(check(date))++ans;
		return;
	}
	if((pos==0&&a[x]==2)||        //将每一位的合法情况进行判断
	   (pos==1&&a[x]==0)||
	   (pos==2&&a[x]==2)||
	   (pos==3&&a[x]==3)||
	   (pos==4&&a[x]>=0&&a[x]<=1)||
	   (pos==5&&a[x]>=0&&a[x]<=9)||
	   (pos==6&&a[x]>=0&&a[x]<=3)||
	   (pos==7&&a[x]>=0&&a[x]<=9))
		dfs(x+1,pos+1,date*10+a[x]);  //选择这个数 
	dfs(x+1,pos,date);  //不选这个数 
}


int main()
{
	ios::sync_with_stdio(0);cin.tie(0); //关闭流同步
	for(int i=0;i<100;i++)cin>>a[i]; 
	dfs(0,0,0);
	cout<<ans;
	
	
	return 0;
}

 答案:235

试题B:01串的熵

【题意分析】

   学会加工题目信息。如果有i个0,那么则有n-i个1.而且0必定比1出现少。所以枚举一半即可。然后可以化成

 填空题枚举就行了!

【复盘代码】

#include<bits/stdc++.h>
using namespace std;
typedef long double db;
const db ans = 11625907.5798,eps=1e-4;
const int N =23333333;
int main()
{
	for(int i=0;i<=N/2;i++)   //0的个数
	{
		int u = N-i;
		db res=-1.0*u*u/N*log2(1.0*u/N)-1.0*i*i/N*log2(1.0*i/N);
		if(fabs(res-ans)<eps){
			cout<<i;
			return 0;
		}	
	}
	return 0;
}

答案:11027421

试题C:冶炼金属

【考试状态】

  这题可能是我最有把握的题目了,一拿到题目,我就想到了逆向分析。然后明确了一个思路。拿一个MAXN数组和一个MINN数组分别保存取下界的值(然后再数组里找一个最小值),MINN数组保存上界值(然后取数组的最大值)。也不知道对不对,只去过了样例。

【考试代码】

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 10010;
int MAXN[N], MINN[N];
int n, k ;
int main()
{
   
    scanf("%d", &n);
    while (n--)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        MAXN[k] = a / b;
        if ((a * 1.0 / (b + 1) > a / (b + 1)))MINN[k] = a / (b + 1) + 1;
        else MINN[k] = a / (b + 1);
        k++;
    }
    sort(MAXN, MAXN + k);
    sort(MINN, MINN + k);
    printf("%d %d", MINN[k - 1] ,MAXN[0]);
    return 0;
}

【复盘代码】二分法:

#include<bits/stdc++.h>
using namespace std;
const int MAX_N=1e4+1;
int N,A[MAX_N],B[MAX_N];
bool check_min(int V)
{
	for(int i=1;i<=N;i++)
		if(A[i]/V>B[i])return false;
	else return true;
}
 
bool check_max(int V)
{
	for(int i=1;i<=N;i++)
	if(A[i]/V<B[i])return false;
	return true;
}
int main()
{
	ios::sync_with_stdio(0);cin.tie(0);
	cin>>N;
	for(int i=1;i<=N;i++)cin>>A[i]>>B[i];
	
	//二分答案过程
	int L=1,R=1000000000,V_min;
	while(L<=R)
	{
		int mid = (L+R)>>1;
		if(check_min(mid)){
			V_min=mid;
			R=mid-1;
		}else L=mid+1;		
	 } 
	 L=1,R=1000000000;int V_max;
	 while(L<=R)
	 {
	 	int mid=L+R>>1;
	 	if(check_max(mid)){
	 		V_max=mid;
	 		L=mid+1;
		 }else R=mid-1;
	 }
	 cout<<V_min<<' '<<V_max;
	 
	return 0;
	
}

试题D:飞机降落

 【题意分析】

  飞机降落问题,看到数据范围的时候,立马想到了贪心模型,想着用全排列的方式去做,数据规模大概在3*10^9,会超时,不过可以过大部分样例。思路是这样,但是考试真的不会写这种排列hh。现在我还记得考试前我复习到的一个全排列函数next_permutation。赛后听到大佬讲用dfs+剪枝的方法可以大大减小数据规模(如果前面某驾飞机已经判断不能降落了,那么就不用再向全排列一样继续枚举),然后跟着大佬去尝试写代码

【复盘代码】dfs+剪枝

#include<bits/stdc++.h>
using namespace std;
const int N = 11;
int T[N],D[N],L[N];
bool used[N],have_answer;    //是否尝试降落,是否有答案 
int n;
void dfs(int x,int tim){	//已经降落了几架,现在所用时间 
	if(have_answer) return; //找到答案,就跳出 
	if(x==n){				//如果降落n架,有解 
		have_answer=1;
		return;
	}
	for(int i=1;i<n;i++)
		if(!used[i]&&tim<T[i]+D[i]){  //没降落,而且现在花费的时间小于这架飞机的最大停留时间 
			used[i]=1;    			 //成功降落 
			dfs(x+1,max(T[i],tim)+L[i]);   //最早在T【i】时间降落,这里取个max值 
			if(have_answer)return;         //找到答案,跳出 
			used[i]=0;					//否则回复原样 
		}
} 

void solve(){
	have_answer=0;   		//开头默认没有解 
	cin>>n;
	for(int i=1;i<=N;i++){
		cin>>T[i]>>D[i]>>L[i];
		used[i]=0;
	}
	dfs(0,0);
	if(have_answer)cout<<"YES\n";
	else cout<<"NO\n";
}

int main()
{
	ios::sync_with_stdio(0);cin.tie(0);
	int t;
	cin>>t;
	while(t--) solve();
	return 0;
}

试题E:接龙数列

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
2023年的第十四届蓝桥杯 C/C++ 大学生大赛 A 省赛是一个非常重要且具有挑战性的比赛。作为蓝桥杯系列赛事的一部分,这个比赛吸引了全国各地的大学生参与,旨在促进青年学生计算机编程技术的提高,培养他们的创新能力和团队协作精神。 参赛者需要通过线上报名,在规定的时间内上传自己的比赛作品。比赛设置了一系列难度逐渐增加的编程题目,要求选手运用C/C++语言进行编写和实现。这些题目可能涉及算法设计、数据结构、编程基础等方面的知识,考察参赛者的编码能力、解决问题的能力以及在压力下的应变能力。 在比赛中,选手不仅需要具备扎实的编程技术,还需要在有限的时间内迅速分析问题、设计解决方案,并通过编程实现。因此,参赛者需要具备良好的逻辑思维能力、数学基础和编程实践经验。 在省赛中取得好成绩的选手将有机会晋级到全国赛,进一步与全国各地的顶尖选手一较高下,争夺更好的名次和更多的奖品。 参加蓝桥杯 C/C++ 大学生大赛不仅是一次锻炼和展示自己编程能力的机会,还能结识更多志同道合的同学和业界精英,获得丰厚的奖金和荣誉。同时,参赛经历对于大学生未来的学习和职业发展也具有积极的影响。 总之,2023年第十四届蓝桥杯 C/C++ 大学生大赛 A 省赛是一个具有挑战性的比赛,参赛者需要具备扎实的编程技术和解决问题的能力。通过参与比赛,学生可以提升自己的编程能力,拓宽视野,展示个人才华,并为未来的学习和就业打下坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值