枚举和模拟算法是计算机领域常用的两种基本算法。枚举算法是一种通过列举所有可能的情况来解决问题的方法。模拟算法则是通过模拟真实场景来解决问题。
枚举、模拟法
枚举算法是指将问题分解为一系列离散的情况,通过枚举所有可能的情况,逐一检查每种情况来解决问题。这种算法适合解决一些问题的最优解问题,但是当数据规模较大时会因为枚举的数量过多而导致运行时间增长。
模拟算法是指将一个问题的真实情况模拟出来,并对问题进行推演,以便得到问题的解决方案。
例如,蓝桥杯 卡片 - 蓝桥云课 (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_string和find去做,详细见我的代码:
我的代码
#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;
}