每日一题 - 231111 - L. Tavern Chess

本文介绍了如何使用C++编写递归函数dfs,解决L.TavernChess中的先手战斗胜利概率计算问题,涉及游戏策略和动态规划思想。
部署运行你感兴趣的模型镜像
//
#include<bits/stdc++.h>
using namespace std;
//#define int long long

const int INF=0x3f3f3f3f;
const int N=15;
int HP[2][N],ATK[2][N],cnt[2][N];
int n,m;
double ans0,ans1,ans_;

int f( bool who )
{
	int idx=0;
	for( int i=1;i<=( who==0 ? n : m );i++ )
		if( HP[who][i]>0 && cnt[who][i]<cnt[who][idx] ) idx=i;
	return idx;
}

void dfs( double p,bool who )
{
	int re_n=0,re_m=0;
	for( int i=1;i<=n;i++ ) re_n+=( HP[0][i]>0 );
	for( int i=1;i<=m;i++ ) re_m+=( HP[1][i]>0 );
	
	if( re_n==0 || re_m==0 )
	{
		if( re_n==0 && re_m==0 ) 	ans_+=p;
		else if( re_n==0 && re_m )	ans1+=p;
		else if( re_n && re_m==0 ) 	ans0+=p;
		return ;
	}
	
	int idx=f(who);
	for( int i=1;i<=( !who==0 ? n : m );i++ )
		if( HP[!who][i]>0 )
		{
			HP[who][idx]-=ATK[!who][i];
			HP[!who][i]-=ATK[who][idx];
			cnt[who][idx]++;
			
			dfs( p/( !who==0 ? re_n : re_m ),!who );
			
			HP[who][idx]+=ATK[!who][i];
			HP[!who][i]+=ATK[who][idx];
			cnt[who][idx]--;
		}
}

void solve()
{
	scanf("%d%d",&n,&m );
	for( int i=1,a;i<=n;i++ ) scanf("%d",&a ),HP[0][i]=ATK[0][i]=a; cnt[0][0]=INF;
	for( int i=1,a;i<=m;i++ ) scanf("%d",&a ),HP[1][i]=ATK[1][i]=a; cnt[1][0]=INF;
	
	if( n>m ) 		dfs( (double)1,0 );
	else if( n<m )	dfs( (double)1,1 );
	else 			dfs( (double)1/2,0 ),dfs( (double)1/2,1 );
	
	printf("%.12lf\n",ans0 );
	printf("%.12lf\n",ans1 );
	printf("%.12lf\n",ans_ );
}

signed main()
{
	solve();
	return 0;	
}
  • Debug:缺少 “else” 导致答案变大
//
#include<bits/stdc++.h>
using namespace std;
//#define int long long

const int INF=0x3f3f3f3f;
const int N=11;
int HP[2][N],ATK[2][N],cnt[2][N];
int n,m;
double ans0,ans1,ans_;

int f( bool who )
{
	cnt[who][0]=INF;
	int idx=0;	// 遍历自己:0 对应 n,1 对应 m
	for( int i=1;i<=( who==0 ? n : m );i++ )
	 	if( HP[who][i]>0 && cnt[who][i]<cnt[who][idx] ) idx=i;
	return idx;
}

void dfs( double p,bool who,int re_n,int re_m,int turn )
{
	// Debug:缺少 "else" 导致答案变大 
	if( !re_n && !re_m ) ans_+=p;			// 平局 
	else if( !re_m ) ans0+=p;				// re_n > 0,re_m == 0,小组 0 胜利 
	else if( !re_n ) ans1+=p;				// re_n == 0,re_m > 0,小组 1 胜利 
	
	/*
		cout<<"p = "<<p<<", who = "<<who<<", !who = "<<(!who)<<", re_n = "<<re_n<<", re_m = "<<re_m<<endl;
		cout<<"ans0 = "<<ans0<<", ans1 = "<<ans1<<", ans_ = "<<ans_<<endl;
		cout<<"ATK:"<<endl;
		for( int i=1;i<=n;i++ ) cout<<ATK[0][i]<<" "; cout<<endl;
		for( int i=1;i<=m;i++ ) cout<<ATK[1][i]<<" "; cout<<endl;
		cout<<"HP:"<<endl;
		for( int i=1;i<=n;i++ ) cout<<HP[0][i]<<" "; cout<<endl;
		for( int i=1;i<=m;i++ ) cout<<HP[1][i]<<" "; cout<<endl;
		if( !( re_n && re_m ) ) cout<<"结束啦"<<endl; 
		cout<<endl;
	*/
	if( !( re_n && re_m ) ) return ;	// 达到结束条件时,return 
	
	int i=f( who );		// 找到最左边攻击次数最少的随从 
	cnt[who][i]++;		// 攻击次数 ++ 
	
	// 遍历对手:0 对应 n,1 对应 m
	for( int j=1;j<=( !who==0 ? n : m );j++ )
	{
		if( HP[!who][j]>0 )
		{
			bool sub_n=0,sub_m=0;
			
			HP[who][i]-=ATK[!who][j];
			if( HP[who][i]<=0 ) 
				who==0 ? sub_n=1 : sub_m=1 ;
			
			HP[!who][j]-=ATK[who][i];
			if( HP[!who][j]<=0 ) 
				!who==0 ? sub_n=1 : sub_m=1 ;
				
//			cout<<"还没有结束哦 cnt = "<<turn<<", "<<who<<" -> "<<(!who)<<", i = "<<i<<", j = "<<j<<endl<<endl;			//
			
			// 遍历对手:0 对应 re_m,1 对应 re_n,镜像对应
			dfs( p/( !who==0 ? re_n : re_m ),!who,re_n-sub_n,re_m-sub_m,turn+1 );
			
			HP[who][i]+=ATK[!who][j];
			HP[!who][j]+=ATK[who][i];
		}
	}
	
	cnt[who][i]--;		// 攻击次数 -- 
}

void solve()
{
	scanf("%d%d",&n,&m );
	for( int i=1,a;i<=n;i++ ) scanf("%d",&a ),HP[0][i]=ATK[0][i]=a;
	for( int i=1,a;i<=m;i++ ) scanf("%d",&a ),HP[1][i]=ATK[1][i]=a;
	
	// n > m 时,小组 0 先手。
	// n < m 时,小组 1 先手。
	// n == m 时,小组 0 先手和小组 1 先手的概率均为 50%
	if( n>m ) dfs( 1,0,n,m,1 );
	if( n<m ) dfs( 1,1,n,m,1 );
	if( n==m ) dfs( (double)1/2,0,n,m,1 ),dfs( (double)1/2,1,n,m,1 ); 
	
	// 误差不超过 1e-9 
	printf("%.12lf\n",ans0 );
	printf("%.12lf\n",ans1 );
	printf("%.12lf\n",ans_ );
}

signed main()
{
	solve();
	return 0;
}

作者 | 乐意奥AI

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值