日期统计(蓝桥杯)

日期统计

问题描述

小蓝现在有一个长度为 100 的数组,数组中的每个元素的值都在 0 到 9 的范围之内。数组中的元素从左至右如下所示:

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

现在他想要从这个数组中寻找一些满足以下条件的子序列:

  1. 子序列的长度为 8;
  2. 这个子序列可以按照下标顺序组成一个 yyyymmdd 格式的日期,并且要求这个日期是 2023 年中的某一天的日期,例如 20230902,20231223。yyyy 表示年份,mm 表示月份,dd 表示天数,当月份或者天数的长度只有一位时需要一个前导零补充。

请你帮小蓝计算下按上述条件一共能找到多少个不同的 2023 年的日期。对于相同的日期你只需要统计一次即可。

答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

答案:235

回溯算法

这段代码实现了一个基于回溯算法的日期统计问题。下面我将对代码进行详细注释。

// 包含常用库文件和命名空间
#include<bits/stdc++.h>
using namespace std;

// ans 用来记录符合条件日期的总数
int ans=0;
// path 用来保存当前正在尝试的日期序列
vector<int> path;
// month 数组用来记录每个月的天数,注意索引0是一个哑元素,从1开始代表1月
int month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};

// 回溯函数,用于生成所有可能的日期序列
void backstracking(int a[],int start)
{
    // 如果路径长度为8,即已经找到一个完整的日期序列
    if(path.size()==8)
    {
        // 检查序列是否以2023年开头
        if(path[0]==2&&path[1]==0&&path[2]==2&&path[3]==3)
        {
            // 从序列中提取出月份
            int mm=path[4]*10+path[5];
            // 检查月份是否在1到12之间
            if(mm>=1&&mm<=12)
            {
                // 从序列中提取出日期
                int dd=path[6]*10+path[7];
                // 检查日期是否在该月可能的日期范围内
                if(dd>=1&&dd<=month[mm])
                {
                    // 如果日期合法,计数器加1
                    ans++;
                }
            }
        }
        // 完整的日期序列已经生成,无需进一步递归,因此返回
        return ;
    }
    // 使用set来避免同一层使用重复的数字
    unordered_set<int> used;
    // 从start位置开始遍历数组
    for(int i=start;i<100;i++)
    {
        // 如果当前数字已经在本层使用过,跳过
        if(used.find(a[i])!=used.end())
            continue;
        // 将当前数字加入到used集合中,表示本层已使用
        used.insert(a[i]);
        // 将当前数字加入到path中
        path.push_back(a[i]);
        // 递归调用回溯函数,从下一个位置开始
        backstracking(a,i+1);
        // 回溯,从path中移除当前数字
        path.pop_back();
    }
}

int main()
{
    // 初始化数组a,包含100个0到9的数字
    int a[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
    };
    
    // 从数组第0个位置开始回溯
    backstracking(a,0);
    // 输出找到的符合条件的日期总数
    cout<<ans;
    return 0;
}

这段代码通过深度优先搜索的回溯方法,尝试所有可能的8位数日期序列,并检查它们是否符合条件。每当找到一个有效的日期时,会将计数器ans增加1。最后,程序输出这个计数器,即符合条件的日期数量。

暴力枚举

此段代码的目的是从一个固定的、包含100个0到9数字的数组中寻找所有符合特定日期格式(即2023年的有效日期)的子序列,并统计这些不同有效日期的数量。以下为详细注释:

// 包含常用的头文件和使用标准命名空间
#include<bits/stdc++.h>
using namespace std;

// 定义month数组,用于存储各月的天数,考虑到不是闰年,所以二月是28天
int month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; // 索引0是占位符
int months[13]; // 用于标记某年某月是否已经被使用

int main()
{
    // a数组包含了100个数字,代表原题中给出的数列
    int a[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
    };
    // 使用set集合res来存储不同的日期,利用集合的特性自动去重
    set<int> res;
    
    // 以下循环结构嵌套层层筛选符合条件的子序列
    
    // 第一层循环,从第一个数字开始,寻找'2',代表年份的千位
    for(int i=0;i<100-7;i++) // 保证后面有足够的数字组成完整日期
    {
        if(a[i]==2)
        {
            // 第二层循环,寻找'0',代表年份的百位
            for(int j=i+1;j<100-6;j++)
            {
                if(a[j]==0)
                {
                    // 第三层循环,寻找'2',代表年份的十位
                    for(int k=j+1;k<100-5;k++)
                    {
                        if(a[k]==2)
                        {
                            // 第四层循环,寻找'3',代表年份的个位
                            for(int l=k+1;l<100-4;l++)
                            {
                                if(a[l]==3)
                                {
                                    // 第五层循环,寻找小于'2'的数,代表月份的十位
                                    for(int o=l+1;o<100-3;o++)
                                    {
                                        if(a[o]<2)
                                        {
                                            // 第六层循环,寻找月份的个位
                                            for(int p=o+1;p<100-2;p++)
                                            {
                                                // 组成月份并检查是否合法
                                                int mm=a[o]*10+a[p];
                                                if(mm>=1&&mm<=12&&months[mm]==0)
                                                {
                                                    // 标记该月份已被使用
                                                    months[mm]=1;
                                                    // 第七层循环,寻找天数的十位
                                                    for(int t=p+1;t<100-1;t++)
                                                    {
                                                        if(a[t]<4)
                                                        {
                                                            // 第八层循环,寻找天数的个位
                                                            for(int y=t+1;y<100;y++)
                                                            {
                                                                // 组成天数并检查是否合法
                                                                int dd=a[t]*10+a[y];
                                                                if(dd>=1&&dd<=month[mm])
                                                                {
                                                                    // 将合法的日期加入集合中
                                                                    res.insert(mm*100+dd);
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    // 输出不同有效日期的数量
    cout<<res.size();
    return 0;
}

这段代码使用了八层嵌套循环来穷举所有可能的日期,每一层循环都是在寻找日期的下一位数字。它使用了一个set来保存所有合法的日期,这样可以自动处理重复日期的问题。程序最终输出了这个集合的大小,即有效日期的总数。注意,程序中的months数组用来标记2023年的每个月是否已经被检查过。

  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

命运从未公平

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

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

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

打赏作者

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

抵扣说明:

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

余额充值