目录
题目一:日期统计:
我的思路——错误代码:
蠢方法:不断使用for循环和if条件语句
#include <bits/stdc++.h>
using namespace std;
int main()
{
// 请在此输入您的代码
int arry[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
}
for(int i=0;i<100;i++)
{
if(arry[i]==2)
{
for(i=i+1;i<100;i++)
if(arry[i]==0)
{
for(i=i+1;i<100;i++)
if(arry[i]==2)
{
for(i=i+1;i<100;i++)
if(arry[i]==3)
{
}
}
}
}
}
return 0;
}
做到这儿,我发现这个代码即没有考虑到子序列的长度为8,满8了之后怎么换下一组呢?而且if语句要考虑大月、小月和2月,这样也太麻烦了!!!还不如直接手动慢慢算,被自己气笑了,但是有一位博主做出来了
蓝桥杯C++之日期统计(两种方法)_蓝桥杯日期统计-CSDN博客
示例代码一
#include <iostream>
#include <set>
using namespace std;
int main() {
int arr[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 month[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
int monthChecke[12] = { 0 };//记录月份访问状态防止重复遍历
set<int> uniqueSet;//利用set去重
for (int i = 0; i < 93; i++) { //年份的第一位只用遍历到倒数第8位即可
if (arr[i] == 2) {
for (int j = i + 1; j < 94; j++ ) { //年份的第一位只用遍历到倒数第7位即可
if (arr[j] ==0) {
for (int k = j + 1; k < 95; k++) {
if (arr[k] == 2) {
for (int l = k + 1; l < 96; l++) {
if (arr[l] == 3) {
for (int a = l+1; a < 97; a++) { //年份的第一位只用遍历到倒数第4位即可
if (arr[a] <2) {// 月份的第一位不能大于2
for (int b = a+1; b < 98; b++) { //月份的第二位
int month1 = arr[a] * 10 + arr[b];
if (0< month1 && month1 <13 && monthChecke[month1-1]==0) { //检查月份是否合法
//记录月份访问状态防止重复遍历
monthChecke[month1-1] = 1;
for (int c = b + 1; c < 99; c++) { //日期的第一位只用遍历到倒数第2位即可
if (arr[c] < 4) {
//日期的第一位不能大于3,可以取0,1,2,3
for (int d = c + 1; d < 100; d++) { //日期的第二位
int day1 = arr[c] * 10 + arr[d];
if (0 < day1 && day1 <= month[month1 - 1]) { //检查日期是否合法
//将得到的日期转化为四位数存入set中去重,年份都是2023,因此不用特殊处理
uniqueSet.insert(arr[a] * 1000 + arr[b] * 100 + arr[c] * 10 + arr[d]);
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
cout << uniqueSet.size() << endl;
return 0;
}
思考:
没有考虑到①遍历重复②8个子序列③没有设置计数器④如何简便的考虑大月、小月、二月
解决办法:
①解决重复问题:
int monthChecke[12] = { 0 };//记录月份访问状态防止重复遍历
if (0< month1 && month1 <13 && monthChecke[month1-1]==0) //检查月份是否合法
//记录月份访问状态防止重复遍历
set<int> uniqueSet;//利用set去重
这里有两个去重的步骤,删除上面的那种不影响结果
②8个子序列
uniqueSet.insert(arr[a] * 1000 + arr[b] * 100 + arr[c] * 10 + arr[d]);
得到的日期转化为四位数存入set中去重,然后遍历下一个8位数
③设置计数器
uniqueSet.size()
.size()可以输出vector类型的长度
④简便考虑大、小月和二月
月份判断:
月份的第一位必须小于2,将第一位和第二位合在一起存为month1,判断month1是否在1~12的范围内
日期的第一位必须不大于3取0,1,2,3,将第一位日期和第二位日期合在一起存为day1,判断day1的范围是否在之前规定的month数组的范围内
知识点总结:
1.set<int> uniqueSet;
容器set是一个元素有序且唯一的关联容器,我们可以利用这一特性实现去重,具体方法就是先将vector内元素拷贝给set,set会自动排序去重,之后再调用vector.assign()函数用set的副本替换vector的元素
在本题的示例中,博主首先头文件声明#include <set>,之后在调用
#include <set>
set<int> uniqueSet;
uniqueSet.insert(arr[a] * 1000 + arr[b] * 100 + arr[c] * 10 + arr[d]);
2..size()
.size()可以输出vector类型的长度
.length()只能输出字符串的长度
这里应该用第一种
3.日期匹配
这里属于思路上的漏洞,当我们再遇到需要固定比较的问题,不妨先设一个数组存储固定的内容,利用下标相互匹配,比较内容
示例方法二
#include <bits/stdc++.h>
using namespace std;
int main()
{
// 请在此输入您的代码
int array[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 daysInMonth[13]={0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int ans=0;
for(int month=1;month<=12;++month)
for(int day=1;day<=daysInMonth[month];++day)
{
int dateSeq[8]={2,0,2,3,month/10,month%10,day/10,day%10};
int k=0;
for(int i=0;i<100;++i)
if(array[i]==dateSeq[k])
{
++k;
if(k==8)
{
ans++;
break;
}
}
}
cout<<ans;
return 0;
}
思考:
①遍历去重复
这个代码没有去重的过程
②8个子序列
if(k==8)
{
ans++;
break;
}
③没有设置计数器
ans
④如何简便的考虑大月、小月、二月
设置dateSeq[]数组,使数组的每一个数字符合逻辑,再将输入的数字匹配dateSeq[]数组
题目二:01串的熵
我的思路:
首先理解题意:
H(S)相当于一个长度为s的01串,其中0有m个,则1就有s-m个,0在s中的占比为p1,1在s中的占比为p2, H(S)的式子可以理解为m×p1xlog2(p1)+(s-m)xp2xlog2(p2)
那么此时转化为一道数学题目:已知长度,已知信息熵,已知公式,我们只需要设一个未知数并求解即可
#include<bits/stdc++.h>
#include <iostream>
using namespace std;
double HS(int s0)
{
double p0=1.0*s0/23333333;
double p1=1.0*(23333333-s0)/23333333;
double hs=1.0*s0*(-p0*log2(p0))+1.0*(23333333-s0)*(-p1*log2(p1));
return hs;
}
int main()
{
// 请在此输入您的代码
for(int i=0;i+i<=23333333;i++)
if(fabs((HS(i)-11625907.5798))<0.0001)
cout<<i;
return 0;
}
错误总结:
①忘记转为浮点数
s0是一个整数int类型的数,而p0、p1是浮点类型的数字,所以在计算时一定要×1.0
double p0=1.0*s0/23333333;
double p1=1.0*(23333333-s0)/23333333;
double hs=1.0*s0*(-p0*log2(p0))+1.0*(23333333-s0)*(-p1*log2(p1));
②未注意到精度问题,注意这里的信息熵一直到第四位,精度也要取到第四位
if(fabs((HS(i)-11625907.5798))<0.0001)
③fabs()对浮点型或者整数类型取绝对值
题目三:冶炼金属
我的思路:
第一种:暴力枚举
以样例为例,v的数值一定小于A即min(75,53,59),遍历这之中的每一个数据,一定有一个最大的数max_v满足75/max_v=3,53/max_v=2,59/max_v=2,同时也存在一个最小的数字min_v满足75/min_v=3,53/min_v=2,59/min_v
#include<bits/stdc++.h>
#include <iostream>
using namespace std;
int main()
{
// 请在此输入您的代码
int max_v=0,min_v=100;
int n;
cin>>n;
int a[100],b[100];
for(int i=0;i<n;i++)
{
scanf("%d %d",&a[i],&b[i]);
}
int min=a[0];
for(int i=1;i<n;i++)
{
if(a[i]<min)
min=a[i];
}
for(int p=1;p<=min;p++)
{
for(int j=0;j<n;j++)
if(a[j]/p==b[j])
{
if(p>max_v) max_v=p;
if(p<min_v) min_v=p;
}
}
printf("%d %d",min_v,max_v);
return 0;
}
这串代码出现了问题,原因是 if(a[j]/p==b[j])这一步没判断是否所有的都符合要求,改一下明天发
标签:arr,set,int,31,s0,蓝桥,省赛题,include From: https://blog.csdn.net/m0_74899987/article/details/137244160