dfs模拟算概率

题目

#include<bits/stdc++.h>
using namespace std;
int cnt[2][10];//攻击次数 
int hp[2][10], atk[2][10], n[2], dead[2];
double win[3], res[3];//win0:0赢的概率,win1:1赢的概率,win2:平局的概率 
void dfs(int op, double p){//当前轮到op攻击,此时概率为p 
	if(dead[op] == n[op] && dead[op ^ 1] == n[op ^ 1]){
		win[2] += p;//分步加法 
		return;
	}
	if(dead[op] == n[op]){
		win[op ^ 1] += p;
		return;
	}
	if(dead[op ^ 1] == n[op ^ 1]){
		win[op] += p;
		return;
	}
	int minn = 1e9; 
	for(int i = 1; i <= n[op]; i++){
		if(hp[op][i] > 0 && cnt[op][i] < minn) minn = cnt[op][i];
	}
	int id, id2;
	for(int i = 1; i <= n[op]; i++){
		if(hp[op][i] > 0 && cnt[op][i] == minn){
			id = i;//找最左的攻击次数最少的人来发动攻击 
			break;
		}
	}
	int rest = n[op ^ 1] - dead[op ^ 1];
    double pp = 1.0 / rest;//选到某个攻击对象的概率 
	for(int i = 1; i <= n[op ^ 1]; i++){
		if(hp[op ^ 1][i] > 0){
			bool f = 0, f2 = 0;
			hp[op ^ 1][i] -= atk[op][id];
			if(hp[op ^ 1][i] <= 0) dead[op ^ 1]++, f = 1;
			hp[op][id] -= atk[op ^ 1][i];
			if(hp[op][id] <= 0) dead[op]++, f2 = 1;
			cnt[op][id]++;
			dfs(op ^ 1, p * pp);//分步乘法 
			//回溯,恢复 
			if(hp[op][id] <= 0) dead[op]--;
			if(hp[op ^ 1][i] <= 0) dead[op ^ 1]--;
			hp[op ^ 1][i] += atk[op][id];
			hp[op][id] += atk[op ^ 1][i];
			cnt[op][id]--;
		}
	}
	
}
int main()
{
	int i;
	cin >> n[0] >> n[1];
	for (i = 1; i <= n[0]; i++)
	{
		cin >> hp[0][i];
		atk[0][i] = hp[0][i];
	}
	for (i = 1; i <= n[1]; i++)
	{
		cin >> hp[1][i];
		atk[1][i] = hp[1][i];
	}
	if(n[0] == n[1]){
		dfs(0, 1);//可能0先手 
		for(int i = 0; i <= 2; i++){
			res[i] += win[i] / 2;//概率权重为1/2 
			win[i] = 0;
		}
		dfs(1, 1);//可能1先手 
		for(int i = 0; i <= 2; i++){
			res[i] += win[i] / 2;//概率权重为1/2 
		}
	}
	else{
		if(n[0] > n[1]){
			dfs(0, 1);
		}
		else dfs(1, 1);
		for(int i = 0; i <= 2; i++){
			res[i] = win[i];
		}
	}
	cout << fixed << setprecision(15) << res[0] << '\n';
	cout << fixed << setprecision(15) << res[1] << '\n';
	cout << fixed << setprecision(15) << res[2] << '\n';
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__night_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值