蓝桥杯刷题冲刺 | 倒计时28天

本文介绍了蓝桥杯竞赛中的几道编程题目,包括用卡片拼数字的问题,解决数字三角形的最大和路径,以及计算购物单所需现金和寻找回文日期。作者分享了自己的解题思路,包括错误和修正过程,强调了审题和边界条件的重要性。
摘要由CSDN通过智能技术生成

作者:指针不指南吗
专栏:蓝桥杯倒计时冲刺

🐾马上就要蓝桥杯了,最后的这几天尤为重要,不可懈怠哦🐾

1.卡片

小蓝有很多数字卡片,每张卡片上都是数字 00 到 99。

小蓝准备用这些卡片来拼一些数,他想从 11 开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。

小蓝想知道自己能从 11 拼到多少。

例如,当小蓝有 3030 张卡片,其中 00 到 99 各 33 张,则小蓝可以拼出 11 到 1010,

但是拼 1111 时卡片 11 已经只有一张了,不够拼出 1111。

现在小蓝手里有 00 到 99 的卡片各 20212021 张,共 2021020210 张,请问小蓝可以从 11 拼到多少?

提示:建议使用计算机编程解决问题。


  • 我的题解

    #include<bits/stdc++.h>
    using namespace std;
    
    int num[10];
    
    int main()
    {
    	int i=0;
    	
    	while(1)
    	{
    		int a=++i;
    		while(a>0)   //取一个数的每一位的做法
    		{
    			num[a%10]++;
    			a/=10;
    		}
    		
    		for(int j=0;j<10;j++)
    		{
    			if(num[j]>2021)
    			{
    				cout<<i-1;  //重点,i的值是取不到的,所以-1!!!!!
    				return 0;
    			}
    		}
    	}
    	
    	
    	return 0;
    }
    

  • 反思

    第一次提交错误是 3182,即当3182时卡片不够用,所以不应该包括 3182

    正确答案 应该是 3181

    可以拿分的题,没了

    考虑边界条件,是否可以取到,是否需要多取一个


2.数字三角形

图片描述

上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。

路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右 边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。

输入描述

输入的第一行包含一个整数N (1≤N≤100),表示三角形的行数。

下面的 N 行给出数字三角形。数字三角形上的数都是 0 至 100 之间的整数。

输出描述

输出一个整数,表示答案。

示例

输入

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

输出

27

  • 我的题解

    • 第一次
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=100;
    
    int d[N][N];
    
    int main()
    {
    	int n;
    	cin>>n;
    	
    	for(int i=0;i<n;i++)
    		for(int j=0;j<=i;j++)
    			cin>>d[i][j];
    			
    	for(int i=n-2;i>=0;i--)
    		for(int j=0;j<=i;j++)
    			d[i][j]+=max(d[i+1][j],d[i+1][j+1]);
    	
    	cout<<d[0][0];
    	
    	return 0;
    }
    

    我觉得我的做法没有问题,而且手算出来答案也是 30,但是样例是 27

    悟了,原因:向左下走的次数与向右下走的次数相差不能超过 1,没有注意这句话

    找到左边界,找到右边界,即连续向左走两步,就只能拐弯

    在这里插入图片描述

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=100;
    
    int d[N][N];
    
    int main()
    {
    	int n;
    	cin>>n;
    	
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=i;j++)
    			cin>>d[i][j];
    			
    	for(int i=2;i<=n;i++)   //从上往下开始找,路径的权值最大的
    		for(int j=1;j<=i;j++)
    			d[i][j]+=max(d[i-1][j],d[i-1][j-1]);
    	
    	cout<<max(d[n][(n+1)/2],d[n][(n+2)/2]);  //最后只能走中间! get这个点
    	
    	return 0;
    }
    
  • 反思

最后一排只能走到 最中间的部分,但是注意 分成 奇数和偶数两种情况

巧妙的方法:

取最中间两个数的,表示方法记住:[(n+1)/2] [(n+2)/2]

认真审题!!注意到每一句话,太重要了


3.购物单

  • 题目

    链接: 购物单 - 蓝桥云课 (lanqiao.cn)

    小明刚刚找到工作,老板人很好,只是老板夫人很爱购物。老板忙的时候经常让小明帮忙到商场代为购物。小明很厌烦,但又不好推辞。

    这不,大促销又来了!老板夫人开出了长长的购物单,都是有打折优惠的。

    小明也有个怪癖,不到万不得已,从不刷卡,直接现金搞定。

    现在小明很心烦,请你帮他计算一下,需要从取款机上取多少现金,才能搞定这次购物。

    取款机只能提供 100 元面额的纸币。小明想尽可能少取些现金,够用就行了。 你的任务是计算出,小明最少需要取多少现金。

    以下是让人头疼的购物单,为了保护隐私,物品名称被隐藏了。

    ****     180.90       88折
    ****      10.25       65折
    ****      56.14        9折
    ****     104.65        9折
    ****     100.30       88折
    ****     297.15        半价
    ****      26.75       65折
    ****     130.62        半价
    ****     240.28       58折
    ****     270.62        8折
    ****     115.87       88折
    ****     247.34       95折
    ****      73.21        9折
    ****     101.00        半价
    ****      79.54        半价
    ****     278.44        7折
    ****     199.26        半价
    ****      12.97        9折
    ****     166.30       78折
    ****     125.50       58折
    ****      84.98        9折
    ****     113.35       68折
    ****     166.57        半价
    ****      42.56        9折
    ****      81.90       95折
    ****     131.78        8折
    ****     255.89       78折
    ****     109.17        9折
    ****     146.69       68折
    ****     139.33       65折
    ****     141.16       78折
    ****     154.74        8折
    ****      59.42        8折
    ****      85.44       68折
    ****     293.70       88折
    ****     261.79       65折
    ****      11.30       88折
    ****     268.27       58折
    ****     128.29       88折
    ****     251.03        8折
    ****     208.39       75折
    ****     128.88       75折
    ****      62.06        9折
    ****     225.87       75折
    ****      12.89       75折
    ****      34.28       75折
    ****      62.16       58折
    ****     129.12        半价
    ****     218.37        半价
    ****     289.69        8折
    

    需要说明的是,88 折指的是按标价的 88 计算,而 8 折是按 80 计算,余者类推。 特别地,半价是按 50计算。

    请输出小明要从取款机上提取的金额,单位是元。

  • 第一次

    #include<bits/stdc++.h>
    using namespace std;
    
    int main()
    {
    	int sum=0;
    	
    	int n=50;
    	
    	int a,b;
    	
    	while(n--)
    	{
    		cin>>a>>b;  //这里,输入很是个问题
    		sum+=a*b;
    	}
    	
    	cout<<sum;
    	
    	return 0;
    }
    

    为了这个输入,我去 word 上去处理 数据,方便它的输入

    一系列的查找替换 处理好 之后 程序 还是不能正确输入

    调式发现 a一直是180

    在这里插入图片描述

    数据类型错了 应该是 double , 我一直写的 int , 最后才发现

    • 第二次——成功
    #include<bits/stdc++.h>
    using namespace std;
    
    int main()
    {
    	double sum=0;
    	
    	int n=50;
    	
    	double a,b;  //数据类型 错了
    	
    	while(n--)
    	{
    		cin>>a>>b;
    		sum+=a*b;
    	}
    	
    	cout<<sum;
    	
    	return 0;
    }
    
    • 通过看题解,还学会了一种方法,这个更加简便
      在这里插入图片描述
  • 反思

    1. 一定要确保数据类型使用正确
    2. 巧用 word 和 excel ,来解答
    3. 看了 python 的题解,tql ,打算简单学习一下 基本语法,填空够用就行

4.回文日期

  • 题目

    链接:回文日期 - 蓝桥云课 (lanqiao.cn)

    2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,恰好是一个回文数。我们称这样的日期是回文日期。

    有人表示 20200202 是 “千年一遇” 的特殊日子。对此小明很不认同,因为不到 2 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。

    也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期。对此小明也不认同,因为大约 100 年后就能遇到下一个 ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。算不上 “千年一遇”,顶多算 “千年两遇”。

    给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。

    输入描述

    输入包含一个八位整数 N*,表示日期。

    对于所有评测用例,10000101≤N≤89991231,保证 N 是一个合法日期的 8 位数表示。

    输出描述

    输出两行,每行 1 个八位数。第一行表示下一个回文日期,第二行表示下一个 ABABBABA 型的回文日期。

    示例

    输入

    20200202
    

    输出

    20211202
    21211212
    
    • 第一次

      #include<bits/stdc++.h>
      using namespace std;
      
      int main()
      {
      	int k;
      	cin>>k;
      	
      	int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
      	
      	int flagh=1,h=0,w=0;
      	
      	int resh,resw;
      	
      	while(!h||!w)
      	{
      		k++;
      		
      		//更新日期 
      		int d=k%100;
      		int m=k%10000/100;
      		int y=k/10000;
      		
      		if(y%4==0&&y%100!=0||y%400==0) a[2]=29;
      		else a[2]=28;
      		
      		if(d>a[m])
      		{
      			d=1,m++;
      		}
      		if(m>12)
      		{
      			m=1,y++;
      		}
      		
      		k=d+m*100+y*10000;
      		
      		//判断满足条件 
      		int t=k;
      		int b[8]={0}; //把每一位放到数组中去
      		 
      		int i=0;
      		while(t>0)
      		{
      			b[i++]=t%10;
      			t/=10;	
      		}
      		
      		//判断回文日期 
      		if(!h)  //表示还没找到 
      		{
      			for(int i=0;i<8;i++)
      			{
      				if(b[i]!=b[8-i-1]) 
      				{
      					flagh=0;  //不是回文,标记1 
      					break;
      				}
      			}
      			if(flagh) 
      			{
      				resh=k;
      				h=1;
      			}
      		}
      		
      		//判断完美日期 
      		if(!w)
      		{
      			int i;
      			if(b[0]==b[2]==b[5]==b[7]&&b[1]==b[3]==b[4]==b[6])
      			{
      				w=1;
      				resw=k;
      			}
      		 } 
      		 
      	 } 
      	 
      	 cout<<resh<<endl<<resw;
      	
      	return 0;
        }
      

      以运行超时告终

    • 第二次

      #include<bits/stdc++.h>
      using namespace std;
      
      bool isleap(int a)
      {
      	return a%4==0&&a%100!=0||a%400==0; 
      }
      
      bool check(int year,int month,int day)
      {
      	if(month==0||month>12) return false;
      	
      	int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
      	
      	if(isleap(year)) a[2]=29;
      	else a[2]=28;
      	
      	if(day>a[month]||day==0) return false;
      	else return true;
      }
      
      int main()
      {
      	int k;
      	cin>>k;
      	
      	int flag=1;
      	
      	for(int i=k+1;i<89991231;i++)
      	{
      			
      		int d=i%100;
      		int m=i%10000/100;
      		int y=i/10000;
      	
      		//判断满足条件 
      		int t=k;
      		int b[8]={0}; //把每一位放到数组中去
      		 
      		int j=0;
      		while(t>0)
      		{
      			b[j++]=t%10;
      			t/=10;	
      		}
      		
      		if(b[0]==b[7]&&b[1]==b[6]&&b[2]==b[5]&&b[3]==b[4]&&flag)
      		{
      			if(check(y,m,d))
      			{
      				cout<<i<<endl;
      				flag=0;
      			}
      			
      		}
      		if(b[0]==b[2]&&b[2]==b[5]&&b[5]==b[7]&&b[1]==b[3]&&b[3]==b[4]&&b[4]==b[6])
      			{
      				cout<<i<<endl;
      				return 0;
      			}	
      	}
      	
      	return 0;
        }
      

      再次以失败告终,但是我就是模拟的正确题解,不知哪里不行

    • 正确题解

      #include <iostream>
      using namespace std;
      
      bool isLeap(int y){
          return (y%4==0&&y%100!=0)||(y%400==0);
      }
      
      bool check(int year,int month,int day){//判断是否为合法日期
          if(month>12||month==0) return false;
          if(day>31) return false;
          if(month==2){
              if(isLeap(year)&&day>29)
                  return false;
              if(!isLeap(year)&&day>28)
                  return false;
          }
          if(month==4||month==6||month==9||month==11){
              if(day>30) return false;
          }
          return true;
      }
      int main()
      {
          int n,i;
          cin>>n;
          int a,b,c,d,e,f,g,h;//8位数字
          int year,month,day;
          bool flag=false;
          for(i=n+1;i<=99999999;i++){
              year=i/10000;
              month=(i%10000)/100;
              day=i%100;
              a=i%10;
              b=(i/10)%10;
              c=(i/100)%10;
              d=(i/1000)%10;
              e=(i/10000)%10;
              f=(i/100000)%10;
              g=(i/1000000)%10;
              h=(i/10000000)%10;
              if(a==h&&b==g&&c==f&&d==e&&flag==false){
                  if(check(year,month,day)){
                      cout<<i<<endl;
                      flag=true;//只输出一个回文
                  }
              }
              if(a==h&&b==g&&c==f&&d==e&&a==c&&b==d){
                  if(check(year,month,day)){
                      cout<<i<<endl;
                      break;
                  }
              }
      
          }
          return 0;
      }
      

Alt

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

指针不指南吗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值