枚举、模拟法(蓝桥杯卡片、数的分解为例)

枚举和模拟算法是计算机领域常用的两种基本算法。枚举算法是一种通过列举所有可能的情况来解决问题的方法。模拟算法则是通过模拟真实场景来解决问题。

枚举、模拟法

枚举算法是指将问题分解为一系列离散的情况,通过枚举所有可能的情况,逐一检查每种情况来解决问题。这种算法适合解决一些问题的最优解问题,但是当数据规模较大时会因为枚举的数量过多而导致运行时间增长。

模拟算法是指将一个问题的真实情况模拟出来,并对问题进行推演,以便得到问题的解决方案。

例如,蓝桥杯 卡片 - 蓝桥云课 (lanqiao.cn)

题目描述

用卡片拼数字拼过的卡片不能再用有 0 到 9 的卡片各 2021 张,共 20210 张请问小蓝可以从 1拼到多少 ?

解题思路

比较容易的模拟,我们从1开始枚举,每次检查剩下的卡片能不能拼出这个数字就好。
把一个数在10进制下每个位置的数字求出来——先对10取模,个位上的数字就求出来了,再除以10,原本十位上的数字就变到了个位上,再对10取模...依次进行下去就求出来了。把当前拼的这个数每一位都拆出来,看看那个数字的卡片还够不够,不够的话就说明拼不了,这时候退出循环,所以最多拼到上一个数

我的代码

#include <iostream>
using namespace std;
int main()
{
  // 请在此输入您的代码
  int a[10]={2021,2021,2021,2021,2021,2021,2021,2021,2021,2021};
  for(int i=0;i<20210;i++){
    int n = i;
        while(n) {
            int d = n % 10;
            if(a[d] == 0) {
                cout << i - 1 << endl;
                return 0;
            }
            a[d]--;
            n /= 10;
        } 
  }
  return 0;
}

例如,蓝桥杯 数的分解 - 蓝桥云课 (lanqiao.cn)

题目描述

把2019分解成3个各不相同的正整数之和,并且要求每个正整数都不包含数字2和4,一共有多少种不同的分解方法?

注意交换3个整数的顺序被视为同一种方法,例如1000+1001+18和1001+1000+18被视为同一种。

解题思路

我们定义这三个各不相同的正整数为i, j, k并且必须满足i<j<k。这样避免重复计算。

我们可以枚举i从1-2019 ,枚举j从1-2019,再枚举k从1-2019,这个题是填空题,这么干没问题,只是三个for循环的复杂度比较高,耗时长一些。

我们可以稍微优化一点点,比如可以考虑最内层的k ,当ij确定了之后,k的值自然就确定了,变成了2个for循环,复杂度就会降低一些,剩下我们只需要检查i,j,k 是否满足题目说的不含2和4即可。

怎么检查呢?

我们可以用字符串的函数to_stringfind去做,详细见我的代码:

我的代码

#include <iostream>
using namespace std;
int main()
{
  // 请在此输入您的代码
  int sum=0,i,j,k;
  for(i=1;i<673;i++)
  {
    for(j=i+1;j<1009;j++)
    {
      k=2019-i-j;
      string a=to_string(i);
      string b=to_string(j);
      string c=to_string(k);
      if(a.find("2")==-1&&a.find("4")==-1&&b.find("2")==-1&&b.find("4")==-1&&c.find("2")==-1&&c.find("4")==-1)
        if(j<k)
          sum++;
    }
  }
  cout<<sum;
  return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值