//
#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
本文介绍了如何使用C++编写递归函数dfs,解决L.TavernChess中的先手战斗胜利概率计算问题,涉及游戏策略和动态规划思想。
384

被折叠的 条评论
为什么被折叠?



