Check the difficulty of problems

博客围绕有m场比赛、t个队伍的比赛场景,求解所有队伍获胜一场及以上且冠军队伍获胜n场及以上的概率。采用概率dp方法,定义了dp和f数组,分析概率情况得出状态转移方程,最终用排除法求解结果,还提醒注意代码初始化。

题目大意:


有m场比赛,t个队伍,告诉你每个队伍每场比赛的胜率,求所有队伍获胜一场及以上且冠军队伍获胜n场及以上的概率。

思路:


很明显的概率 dpdpdp

先定义:

dp[i][j]dp[i][j]dp[i][j] 为第iii个队伍在前jjj道题中恰好做了kkk道题的概率。

因为题意要求所有队伍获胜一场及以上且冠军队伍获胜n场及以上的概率;

所以我们还需要一个数组 f[i][j]f[i][j]f[i][j] 来存储第iii个队至多做出jjj题的概率。

接下来分析概率情况:

对于任意队伍而言,一道题只有两种结果:

做对 or 没做对

那么状态转移方程就很好想了 :

  • p1=dp[i][j−1][k−1]∗p[i][j]p1 = dp[i][j - 1][k - 1] * p[i][j]p1=dp[i][j1][k1]p[i][j];
  • p2=dp[i][j−1][k]∗(1−p[i][j])p2 = dp[i][j - 1][k] * (1 - p[i][j])p2=dp[i][j1][k](1p[i][j]);
  • dp[i][j][k]=p1+p2dp[i][j][k] = p1 + p2dp[i][j][k]=p1+p2;

解释:

  • p1p1p1 :第 jjj 到题做对,此时一共做对 kkk 道题,因此需要乘上 dp[i][j−1][k−1]dp[i][j - 1][k - 1]dp[i][j1][k1] (iii队在前 j−1j - 1j1 场比赛做对 k−1k - 1k1 道题的概率);
  • p2p2p2 参考 p1p1p1 的解释;
  • 总概率为两种情况概率的总和。

最终答案:


因为 dpdpdp 的状态定义,最终结果的求解方法自然而然地选择了排除法(即用总概率 −- 不符合情况的概率

  • 总概率 :$ \prod_{i=1}^t (f[i][m] - f[i][0])$ ;
  • 不符合情况的概率:$ \prod_{i=1}^t (f[i][n - 1] - f[i][0])$ ;

解释:

  • 总概率:共有 mmm 场比赛,那么所有符合题意的情况的概率就为 ttt 个队伍做对 111mmm 道题的概率之积,用至多作对 mmm 道题的概率减去至多做对 000 道题的概率,即为做对 111mmm 道题的概率
  • 不符合情况的概率:参考总概率的解释

完整代码:
PSPSPS:注意初始化!!!


#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 150;
int n,m,t;
double dp[1005][35][35],f[1005][1005],p[1005][35];
//p[i][j] 第i个队通过第j题的概率
int main() {
	while(scanf("%d %d %d",&m,&t,&n) != EOF && m != 0 && t != 0 && n != 0) {
		memset(dp,0,sizeof(dp));
		memset(f,0,sizeof(f));
		for(int i = 1; i <= t; i ++) {
			for(int j = 1; j <= m; j ++) scanf("%lf",&p[i][j]);
		}
		for(int i = 1; i <= t; i ++) {
			dp[i][0][0] = 1;//一道题没做 
			for(int j = 1; j <= m; j ++) {
				dp[i][j][0] = dp[i][j - 1][0] * (1 - p[i][j]); //没做对题 
			}
		}
		for(int i = 1; i <= t; i ++) {
			for(int j = 1; j <= m; j ++) {
				for(int k = 1; k <= j; k ++) {
					dp[i][j][k] = dp[i][j - 1][k - 1] * p[i][j] + dp[i][j - 1][k] * (1 - p[i][j]);//两种情况:第j道题做对和没做对 
				}
			}
		}
		for(int i = 1; i <= t; i ++) {
			for(int j = 0; j <= m; j ++) {
				if(j != 0 ) f[i][j] = f[i][j - 1] + dp[i][m][j]; 
				else f[i][j] = dp[i][m][0];
			}
		}
		double p1 = 1, p2 = 1;
		for(int i = 1; i <= t; i ++) {
			p1 *= (f[i][m] - f[i][0]); 
			p2 *= (f[i][n - 1] - f[i][0]);
		}
		printf("%.3lf\n",p1 - p2);
	}
	return 0;
}
# T671331 [ZJCPC 2017] Problem Preparation ## 题目描述 It's time to prepare the problems for the $14$-th Zhejiang Provincial Collegiate Programming Contest! Almost all members of SUA programming contest problem setter team brainstorm and code day and night to catch the deadline, and empty bottles of $\textit{Marjar Cola}$ litter the floor almost everywhere! To make matters worse, one of the team member fell ill just before the deadline. So you, a brilliant student, are found by the team leader Dai to help the team check the problems' arrangement. Now you are given the difficulty score of all problems. Dai introduces you the rules of the arrangement: - The number of problems should lie between $10$ and $13$ (both inclusive). - The difficulty scores of the easiest problems (that is to say, the problems with the smallest difficulty scores) should be equal to $1$. - At least two problems should have their difficulty scores equal to $1$. - After sorting the problems by their difficulty scores in ascending order, the absolute value of the difference of the difficulty scores between two neighboring problems should be no larger than $2$. BUT, if one of the two neighboring problems is the hardest problem, there is no limitation about the difference of the difficulty scores between them. The hardest problem is the problem with the largest difficulty score. It's guaranteed that there is exactly one hardest problem. The team members have given you lots of possible arrangements. Please check whether these arrangements obey the rules or not. ## 输入格式 There are multiple test cases. The first line of the input is an integer $T$ ($1 \le T \le 10^4$), indicating the number of test cases. Then $T$ test cases follow. The first line of each test case contains one integer $n$ ($1 \le n \le 100$), indicating the number of problems. The next line contains $n$ integers $s_1, s_2, \dots, s_n$ ($-1000 \le s_i \le 1000$), indicating the difficulty score of each problem. We kindly remind you that this problem contains large I/O file, so it's recommended to use a faster I/O method. For example, you can use scanf/printf instead of cin/cout in C++. ## 输出格式 For each test case, output "Yes" (without quotes) if the arrangement follows the rules, otherwise output "No" (without quotes). ## 输入输出样例 #1 ### 输入 #1 ``` 8 9 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 11 999 1 1 2 3 4 5 6 7 8 9 11 999 1 3 5 7 9 11 13 17 19 21 10 15 1 13 17 1 7 9 5 3 11 13 1 1 1 1 1 1 1 1 1 1 1 1 2 10 2 3 4 5 6 7 8 9 10 11 10 15 1 13 3 6 5 4 7 1 14 ``` ### 输出 #1 ``` No No Yes No Yes Yes No No ``` ## 说明/提示 The first arrangement has $9$ problems only, which violates the first rule. Only one problem in the second and the fourth arrangement has a difficulty score of $1$, which violates the third rule. The easiest problem in the seventh arrangement is a problem with a difficulty score of $2$, which violates the second rule. After sorting the problems of the eighth arrangement by their difficulty scores in ascending order, we can get the sequence $\{1, 1, 3, 4, 5, 6, 7, 13, 14, 15\}$. We can easily discover that $|13-7| = 6 > 2$. As the problem with a difficulty score of $13$ is not the hardest problem (the hardest problem in this arrangement is the problem with a difficulty score of $15$), it violates the fourth rule.
最新发布
09-30
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值