0
点赞
收藏
分享

微信扫一扫

蓝桥杯刷题日记

蛇发女妖 2022-01-18 阅读 98

算法训练 印章

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

解法:

这题要用二维的动态规划来做,建立一个二维数组dp[m][n],开始的时候以为dp[i][1],应该为1,因为买m枚印章肯定会出现1种,后来看了别人的题解发现想错了,dp[i][j]表示的是买i枚里面有j种的概率,而不是买i枚至少有j枚的概率。

而中间态可以分为两种情况,一种是前i-1个已经凑齐n种,一种是前i-1个凑齐i-1种,故可得状态转移方程如下:

#include<stdio.h>
#include <cmath>
int main()
{
	int n, m;
	scanf_s("%d%d", &n, &m);
	double dp[25][25], p;
	p = 1.0 / n;
		for (int i = 1; i <= m; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				if (i < j)
				{
					dp[i][j] = 0.0;
				}
				else if (j == 1)
				{
					dp[i][j] = pow(p, i - 1);
				}
				else {
					dp[i][j] = dp[i - 1][j] * (j * 1.0 / n) + dp[i - 1][j - 1] * ((n - j + 1) * 1.0 / n);
				}
			}
		}
	
		printf("%.4lf", dp[m][n]);
	return 0;
}

算法训练  拿金币

有一个N x N的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。

解法:

简单的dp解法,用一个二维数组存到达每个格子可拿的最大金币数,最终dp[n-1][n-1],即为最优解。

#include<stdio.h>
int max[1005][1005];
int main()
{
	int n;
	scanf_s("%d", &n);
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			scanf_s("%d", &max[i][j]);
		}
	}
	for (int i = 1; i < n; i++)
	{
		max[i][0] += max[i - 1][0];
		max[0][i] += max[0][i - 1];
	}
	for (int i = 1; i < n; i++)
	{
		for (int j = 1; j < n; j++)
		{
			if (max[i][j - 1] > max[i - 1][j])
			{
				max[i][j] += max[i][j - 1];
			}
			else
			{
				max[i][j] += max[i - 1][j];
			}
		}
	}
	printf("%d", max[n - 1][n - 1]);
	return 0;
}
举报

相关推荐

0 条评论