蓝桥杯DAY2+3-2.27+2.28

本文介绍了如何使用C++通过暴力搜索的方法,遍历给定数字组合以找出2023年的合法日期,并使用set数据结构进行去重。首先展示了逐个数字组合年份的法一,然后介绍了优化后的法二,即生成全年日期后查找给定数字。
摘要由CSDN通过智能技术生成

目录

1.日期统计

法一:暴力搜所有数字,看能否组合成合法日期。

1.set ans;是什么意思

2.为什么4个for循环这么写,遍历年份

3.m、n用于表示月份,而o、p用于表示日期。

这是因为在循环中,m从v+1开始递增,n从m+1开始递增,所以m和n的组合可以表示一个两位数的月份。同样地,o从n+1开始递增,p从o+1开始递增,所以o和p的组合可以表示一个两位数的日期。通过这种方式,代码遍历了所有可能的月份和日期组合。所以无所谓哪个用哪个。

4.ans.insert(temp);

5.注意break的位置,一念之差就是0%与100%!

6.为什么要写break,且为什么break的位置是在那里?

法二:更好的暴力法,是反过来操作。不是在100个数字中找出8个来构成合法日期,而是生成2023年的365个日期,看有多少能在100个数字中找到。

1.年份、月份和日期拼接成一个字符串

2.函数 to_string()

3.ans++

总结:



本文中部分解释出自讯飞星火 


1.日期统计

方法和代码摘自罗老师的博客,链接如下:<蓝桥杯软件赛>零基础备赛20周--第3周--填空题-CSDN博客

法一:暴力搜所有数字,看能否组合成合法日期。

#include<bits/stdc++.h>
using namespace std;

int num[100]= {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
              };
int days[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31};

int main() {

	set<int> ans;
	for(int i=0; i<100; i++) {
		for(int j=i+1; j<100; j++) {
			for(int k=j+1; k<100; k++) {
				for(int v=k+1; v<100; v++) { //前四个数构成年
					int y=num[i]*1000+num[j]*100+num[k]*10+num[v]; //年

					if(y==2023) { //找到了年,再找月和日
						for(int m=v+1; m<100; m++) {
							for(int n=m+1; n<100; n++) {
								for(int o=n+1; o<100; o++) {
									for(int p=o+1; p<100; p++) {
										int mon=num[m]*10+num[n]; //月
										int d=num[o]*10+num[p]; //日
										if((mon>=1 && mon<=12) && (d>=1 && d<=days[mon])) {
											int temp=mon*100+d;
											ans.insert(temp); //将temp添加到ans集合中,并自动去重(set的功能)
										}
									}

								}
							}
						}
						break; //一念之差,0%与100% 
					}
				}
			}
		}
	}
	cout<<ans.size();
	return 0;
}

1.set<int> ans;是什么意思

`set<int> ans;` 是C++中的一种声明方式,表示定义了一个名为 `ans` 的集合(Set),其中的元素类型为整数(int)。

集合的特点就是不会出现重复的内容。一般用来作查重去重操作

在C++中,`set` 是一种关联容器,它存储唯一元素,并且按照元素的值进行排序。`set` 提供了快速查找、插入和删除操作,并且不允许重复元素。

通过声明 `set<int> ans;`,你可以创建一个空的整数集合 `ans`,用于存储整数值。你可以在后续的代码中使用这个集合进行各种操作,例如添加元素、删除元素、遍历集合等。

详细见这篇博客c++ set用法 入门必看 超详细-CSDN博客

2.为什么4个for循环这么写,遍历年份

 for (int i = 0; i < 100; i++)
        for (int j = i + 1; j < 100; j++)
            for (int k = j + 1; k < 100; k++)
                for (int v = k + 1; v < 100; v++) {//前4个数字构成年
                    int y = num[i] * 1000 + num[j] * 100 + num[k] * 10 + num[v];//年
}

这段代码中的for循环嵌套了四个循环,每个循环都使用了一个变量来控制循环的执行次数。这种写法通常用于处理多维数组或需要多次迭代的情况。

在这个例子中,前四个数字被用来构成年份。外层循环变量i从0开始递增,内层循环变量j从i+1开始递增,依此类推。这样的写法可以确保每次循环迭代时,变量的值都是唯一的,并且满足特定的条件。

具体来说,这个代码段的作用是遍历所有可能的年份组合,其中前四个数字表示年份。通过嵌套循环的方式,可以生成所有可能的年份组合,并进行相应的处理或计算。

在这段代码中,变量j从i+1开始递增的原因是为了避免重复的组合和确保每个数字只被使用一次

具体来说,这段代码的目的是生成所有可能的年份组合,其中前四个数字表示年份。为了确保每个年份都是唯一的,我们需要避免重复的数字组合。通过让变量j从i+1开始递增,我们可以确保每次循环迭代时,j的值都大于i,从而避免了重复的组合。这样的写法可以保证生成的所有年份组合都是唯一的,并且每个数字只被使用一次。

3.m、n用于表示月份,而o、p用于表示日期。

这是因为在循环中,m从v+1开始递增,n从m+1开始递增,所以m和n的组合可以表示一个两位数的月份。同样地,o从n+1开始递增,p从o+1开始递增,所以o和p的组合可以表示一个两位数的日期。通过这种方式,代码遍历了所有可能的月份和日期组合。所以无所谓哪个用哪个。

题目要求20230412这种形式,04是月,12是日,他的遍历顺序m和n在op前面,mn就是月,op就是日

4.ans.insert(temp);

`ans.insert(temp);` 是一行代码,它表示将变量 `temp` 插入到名为 `ans` 的集合中。

根据上下文的不同,`ans` 可能是一个数组、向量(vector)、列表(list)或其他支持插入操作的数据结构。`temp` 是要插入的元素或对象。

这行代码的作用是将 `temp` 添加到 `ans` 集合中,并自动去重(set的功能)。如果 `temp` 已经存在于 `ans` 中,则不会重复添加。这样可以确保 `ans` 中的元素是唯一的。

5.注意break的位置,一念之差就是0%与100%!

6.为什么要写break,且为什么break的位置是在那里?

如果break紧跟在 ans.insert(temp);的后面才是只找到一个就停止
现在break跟在了if的for都结束的时候,所以2023年在break这个时候其实已经都找完了。

7.注意找完之后,在写四层循环,此时第一层是从年的第四层循环+1开始写。

也就是代码中的int m=v+1;
 

法二:更好的暴力法,是反过来操作。不是在100个数字中找出8个来构成合法日期,而是生成2023年的365个日期,看有多少能在100个数字中找到。

#include<bits/stdc++.h>
using namespace std;

int num[110]= {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
              };
int days[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31};

int main() {
	int ans=0;
	for(int i=1; i<=12; i++) {
		for(int j=1; j<=days[i]; j++) {
			string str="2023"; //年
			if(i<10) {
				str+="0"; //字符串加就是双引号,下面的数字与字符串转换就是单引号
			}
			str+=to_string(i); //+月
			if(j<10) {
				str+="0";
			}
			str+=to_string(j); //+日
			int k=0;
			for(int v=0; v<100 && k<8; v++) { //在100个数中找这个日期
				if(num[v]==str[k]-'0') {
					k++;
				}
			}
			if(k>=8) {
				ans++;
			}
		}

	}
	cout<<ans<<endl;
	return 0;
}

其中这一些:

for (int i = 1; i <= 12; i++) {
        for (int j = 1; j <= days[i]; j++) {
            string str = "2023";    //年
            if (i < 10)  str += "0";
            str += to_string(i);     //+月
            if (j < 10)str += "0";
            str += to_string(j);     //+日
            int k = 0;
            for (int v = 0; v < 100 && k < 8; v++)  //在100个数中找这个日期
                if (num[v] == str[k] - '0')
                    k++;
            if (k >= 8) ans++;
        }
    }

1.年份、月份和日期拼接成一个字符串

这段代码是一个嵌套循环,用于生成2023年的所有日期外层循环遍历月份(1到12)内层循环遍历每个月的天数(1到该月的天数)在每次循环中,将年份、月份和日期拼接成一个字符串,然后检查这个字符串是否包含给定的8个数字。如果包含,则计数器ans加1。最后输出ans的值,即满足条件的日期数量。

2.函数 to_string()

to_string 函数:将数字常量转换为字符串,返回值为转换完毕的字符串.

3.ans++

必须8位全部满足,k才等于8;这样ans才要++。如果8位中前几位满足,后来的不满足,那么k就到不了8,ans也就不会++。


总结:

1.无重复的遍历年份的代码模板:

 for (int i = 0; i < 100; i++)
        for (int j = i + 1; j < 100; j++)
            for (int k = j + 1; k < 100; k++)
                for (int v = k + 1; v < 100; v++) {//前4个数字构成年
                    int y = num[i] * 1000 + num[j] * 100 + num[k] * 10 + num[v];//年
}

2.拿到题解代码时先提交试试确定是不是对的!!!

3.+"0"与+‘0’的区别

 字符串加就是双引号,数字与字符串转换就是单引号

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值