蓝桥杯算法训练 印章

蓝桥杯 算法训练 印章

问题描述

​ 共有n种图案的印章,每种图案的出现概率相同。小A买了m张印章,求小A集齐n种印章的概率。

输入格式

​ 一行两个正整数n和m

输出格式

​ 一个实数P表示答案,保留4位小数。

样例输入

​ 2 3

样例输出

​ 0.7500

数据规模和约定

1≤n,m≤20

本题使用动态规划算法,动态规划无非是以下三步,

  • 确认状态,即dp数组中的值的含义
  • 设计状态转移方程(递推公式)。
  • 设置dp数组的初值

其中前2步尤为关键。除此之外,对于同一个问题使用用动态规划算法,可以设计出不同的状态和对应的状态转移方程(即dp数组所代表的含义和递推公式不唯一)

解题思路

首先,题目说买m个印章,凑齐n种不同的印章。有2个变量,自然的想到使用二维数组(一般的题目都是用二维数组),而题目是求买m个印章,集齐n种印章的概率。所以可以用dp[i][j]代表买i个印章,集齐j种印章的概率

于是就有了以下表格

dp(i,j):

(1,1)(1,2)(1,3)(1,4)
(2,1)(2,2)(2,3)(2,4)
(3,1)(3,2)(3,3)(3,4)
(4,1)(4,2)(1,3)(4,4)

分析

在这里插入图片描述

  • 红色圈内,当j=1时,总共只有1种印章,无论买多少个印章都必定可以凑齐,所以概率p=1
  • 橙色圈内,当i<j时,购买买的印章数量少于印章的种类数,不可能凑齐,概率p=0

所以,只剩下绿色圈内的值未知,需要使用状态转移方程求出。

在求dp[i][j]时,需要思考它与dp数组中其他值的关系。由概率论相关知识可知,当求买m个印章,凑不齐(注意是凑不齐)n种印章的
概率时,买到的印章共有i^m 种结果,即分母为 i^m。分子则为 ∑ k = 1 i − 1 ( C i k k m d p [ i ] [ k ] ) \sum_{k=1}^{i-1}(C_i^kk^mdp[i][k]) k=1i1(Cikkmdp[i][k])
凑齐的概率则为(1-凑不齐的概率)
由此可以看出分子只与dp数组的某一行有关,所以其实只需要一维数组就可以了,一维数组的值代表凑齐n种印章的概率。(购买的印章数量固定不变)

以买4个印章凑齐n种为例
在这里插入图片描述

所以购买m个印章,凑齐i种印章的概率dp[i]
d p [ i ] = ∑ k = 1 i − 1 ( C i k k m d p [ k ] ) i m dp[i]=\frac{\sum_{k=1}^{i-1}(C_i^kk^mdp[k])}{i^m} dp[i]=imk=1i1(Cikkmdp[k])
具体代码如下:

#include<stdio.h>
#include<math.h>
double dp[22];//一维数组,dp[i]:买i张印章,凑齐n种印章的概率 
/*
为什么用一维数组?
因为在此解法所用的递推公式中, 
买m张印章,凑齐n种印章的概率只与买m张印章,凑齐n-1种,n-2种...1种 的概率有关 , 
与买x(x!=m)张印章凑齐y(y>=1)种印章的概率无关 
*/ 
long long c_fun(int n,int m)//求组合数C(n,m); 
{
	long i;
	long long ans_n=1,ans_m=1,ans_nm=1;
	for(i=2;i<=n;i++)
		ans_n=ans_n*i;
	for(i=2;i<=m;i++)
		ans_m=ans_m*i;
	for(i=2;i<=n-m;i++)
		ans_nm=ans_nm*i;
	return ans_n/(ans_m*ans_nm);
	
} 
double fun(int n,int m)//求解印章问题 
{
	int i,j;
	double t=0;
	dp[1]=1.0;//只需凑齐1种,必定可以凑齐 
	for(i=2;i<=n;i++)//循环,计算需凑齐2,3,4...n种的情况 
	{
		t=0;
		for(j=1;j<i;j++)// 
		{
			t=t+c_fun(i,j)*dp[j]*pow(j,m);//递推公式 
					
		}
		dp[i]=1-t/pow(i,m);
		//要用1去减,因为前面递推公式计算出来的是凑不齐的概率,dp数组存的是凑齐的概率 
	}
	return dp[n];//返回结果 
} 
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);//共n种印章,买m张 
	fun(n,m);//求解 
	printf("%.4lf\n",dp[n]);//dp[n]即为结果 
	return 0;
}

另一种解法:使用二维数组,dp[i] [j]表示买 i 张凑齐 j 种印章的概率,具体请看另一篇博客蓝桥杯 算法训练 印章

总结:

对于动态规划最重要的就是画图填表,求递推方程。除此之外,通往罗马的路不止一条,对于一个问题,看问题的角度不同就会有不同的解法。

  • 21
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值