[POJ2238]Computer Basketball Game && 概率DP

本文介绍了一个使用动态规划算法模拟篮球比赛得分概率的程序。通过设定球员的投篮能力及篮板球概率,该程序能够计算出特定时间内两队得分的概率分布,并最终确定获胜队伍的概率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

结合代码注释理解一下吧 感觉写的很详细了- - 

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<cmath>
#include<deque>
#define SF scanf
#define PF printf
using namespace std;
typedef long long LL;
const int MAXN = 40;
double f[MAXN+10][MAXN+10][2];
int p21, p31, d1, r1, p22, p32, d2, r2;
int n, m;
double ans;
void dp() {
	double t31 = 1.0 * p31 / (p31 + p21); // 第一个人投三分
	double m31 = 0.8 * p31 / (p31 + d2);  // 第一个人三分命中
	double m21 = 1.0 * p21 / (p21 + d2);  // 第一个人投两分命中
	double g1 = 0.8 * r1 / (r1 + r2);     // 第一个人投球失败但抢球成功
	double t32 = 1.0 * p32 / (p32 + p22);
	double m32 = 0.8 * p32 / (p32 + d1);
	double m22 = 1.0 * p22 / (p22 + d1);
	double g2 = 0.8 * r2 / (r1 + r2);
	
	double P31 = t31 * m31;  // 第一个人投三分并命中
	double P21 = (1-t31) * m21; // 第一个人投两分并命中
	double Pr1 = g1 * (1 - P31 - P21); // 第一个人未命中但抢球成功
	double Pf1 = (1-g1) * (1-P31-P21); // 第一个人未命中且抢球失败
	double P32 = t32 * m32;
	double P22 = (1-t32) * m22;
	double Pr2 = g2 * (1 - P32 - P22);
	double Pf2 = (1-g2) * (1-P32-P22);
	
	double ok31 = P31 / (1 - Pr1); // 在第一个人不听重复“未命中->抢球成功"过程后投三分并命中 (1+Pr1+...+Pr1^n) * P31 = P31 / (1-Pr1)
	double ok21 = P21 / (1 - Pr1); // 在第一个人不听重复“未命中->抢球成功"过程后投两分并命中
	double okf1 = Pf1 / (1 - Pr1); // 在第一个人不听重复“未命中->抢球成功"过程后抢球失败
	double ok32 = P32 / (1 - Pr2);
	double ok22 = P22 / (1 - Pr2);
	double okf2 = Pf2 / (1 - Pr2);
	memset(f, 0, sizeof(f));
	for(int i = n; i < 34; i++)
		for(int j = 0; j < n; j++) {
			f[i][j][0] = f[i][j][1] = 1;
			f[j][i][0] = f[j][i][1] = 0;
		}
	for(int i = n-1; i >= 0; i--)
		for(int j = n-1; j >= 0; j--) {
			double trans1 = ok31 * f[i+3][j][0] + ok21 * f[i+2][j][0];
			double trans2 = ok32 * f[i][j+3][1] + ok22 * f[i][j+2][1];
			f[i][j][0] = (trans1 + trans2 * okf1) / (1 - okf1 * okf2); // 两个人不停重复交换控球权概率 (1 + okf1*okf2 + (okf1*okf2)^2 +....+ (okf1*okf2)^n) = 1 / (1 - okf1 * okf2)
			f[i][j][1] = (trans2 + trans1 * okf2) / (1 - okf1 * okf2);
		}
	ans = max(ans, f[0][0][0]);
}
int main() {
	while(~SF("%d%d%d%d%d%d", &n, &m, &p22, &p32, &r2, &d2)) {
		ans = 0;
		for(p21 = 1; p21 <= 10; p21++) {
			if(m-p21 < 3) break;
			if(m-p21 > 30) continue;
			for(p31 = 1; p31 <= 10; p31++) {
				if(m-p21-p31 < 2) break;
				if(m-p21-p31 > 20) continue;
				for(d1 = 1; d1 <= 10; d1++) {
					if(m-p21-p31-d1 < 1) break;
					if(m-p21-p31-d1 > 10) continue;
					r1 = m-p21-p31-d1;
					dp();
				}
			}
		}
		PF("%.3f\n", ans);
	}
}
/*
20 21 3 5 6 6
21 21 3 5 6 6
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值