最清晰易懂的MinMax算法和Alpha-Beta剪枝详解-CSDN博客
MinMax的算法流程就是
(1)首先构建整个博弈树
(2)题设肯定就是一个人和另外一个人进行交替选择进行的步骤。那么每一层对应一个min和max。min就是最小化对手的选择,max就是最大化自己的选择。
(3)整个算法流程是先从上到下遍历到每一个叶子节点,算出每一个叶子节点的估计价值。然后从下网上进行一层层的minmax取值。直到最后的根层。
(4)最后从下面的传递上来的估计函数价值就是最后的结果。如果想要找到路径,那么就是从根节点 对应每一层选取minmax的数值。然后就可以选出这一条路径。
例题:
A-Cake_2024牛客暑期多校训练营6 (nowcoder.com)
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+100;
vector<double>dp(N);
vector<double>ans(N);
vector<int>sum0(N),d(N);
vector<pair<int,int>>e[N];
void dfs(int u,int fa,int dep){
double minn=2,maxx=-1;
for(auto [v,w]:e[u]){
if(fa==v) continue;
sum0[v]=sum0[u];
if(w==0) sum0[v]++;
dp[v]=(double)sum0[v]/(double)(dep+1);
dp[v]=max(dp[v],dp[u]); //因为随时可以选择最大的0占比所以可以这样
dfs(v,u,dep+1);
minn=fmin(minn,ans[v]);
maxx=fmax(maxx,ans[v]);
}
if(minn==2&&maxx==-1){
ans[u]=dp[u];
return;
}
if(dep&1) ans[u]=maxx;
else ans[u]=minn;
}
void solve(){
int n;cin>>n;
for(int i=1;i<=n;i++){
sum0[i]=0;
e[i].clear();
}
for(int i=1;i<n;i++)
{
int x,y,w;cin>>x>>y>>w;
e[x].push_back({y,w});
e[y].push_back({x,w});
}
dfs(1,0,0);
cout<<setprecision(12)<<1-ans[1]<<"\n";
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
}