题目一:
问题描述
共有n种图案的印章,每种图案的出现概率相同。小A买了m张印章,求小A集齐n种印章的概率。
输入格式
一行两个正整数n和m
输出格式
一个实数P表示答案,保留4位小数。
样例输入
2 3
样例输出
0.7500
拿到这题第一个思路是排列组合求概率,
由题目可知当n=1时概率p为1.n>m p=0.当n>m时,概率p为0动态规划p[i][j]代表买i枚里面有j种的概率
拿到每一种的概率p=1/n
1、if i<j dp[i][j] = 0
2、if j=1 dp[i][1]=pow(p, i - 1)
不是n=1,dp[i][1]=1
代表买i枚里面有1种的概率
3、中间态:
一种是前i-1个已经集齐n种,这时j可随意取,概率为j*p
一种是前i-1个集齐i-1种,这个时候j只能取前面缺少的哪一个,【n-(j-1)】*p代码如下:
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
double dp[21][21];
double 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);
}
}
}
cout<<fixed<<setprecision(4)<<dp[m][n]<<endl;
return 0;
}
题目二:
问题描述
有一个N x N的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。
输入格式
第一行输入一个正整数n。
以下n行描述该方格。金币数保证是不超过1000的正整数。
输出格式
最多能拿金币数量。
样例输入
3
1 3 3
2 2 2
3 1 2
样例输出
11
当前格子可以由它上面格子走来,或者它左面
a[i][j]+=max{a[i-1][j],a[i][]j-1}代码如下:
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int a[1001][1001];
int main()
{
int n,i,j;
cin>>n;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
cin>>a[i][j];
}
/*
当前格子可以由它上面格子走来,或者它左面
对于第一行,只能由它左面走来a[i][j]+=a[i][j-1]
对于第一列,只能由它上面走来a[j][i]+=a[j-1][i];
*/
for(i=0,j=1;j<n;j++)
{
a[i][j]+=a[i][j-1];
a[j][i]+=a[j-1][i];
}
for(i=1;i<n;i++)
for(j=1;j<n;j++)
{
if(a[i-1][j]>a[i][j-1])
a[i][j]+=a[i-1][j];
else
a[i][j]+=a[i][j-1];
}
cout<<a[n-1][n-1]<<endl;
return 0;
}