K - Knockout Tournament 递归,暴力求解
题目大意:
这个题目大意有点难说明,还是自己理解的好。
如果n=10,那么就是比赛一定是上面的图的形式。
题解:
先读懂题目大意,找到一个合理的递归方式,然后暴力求每一个可能,往上回传一个vector数组。
思维不大,主要题目要看懂!
#include <bits/stdc++.h>
using namespace std;
#define PI acos(-1)
const int maxn = 5e3+10;
typedef long long ll;
double p[maxn];
ll a[maxn];
struct node{
int id;
double p;
node(int id=0,double p=0):id(id),p(p){}
};
void print(vector<node> ans){
int len = ans.size();
for(int i=0;i<len;i++) printf("id = %d p = %f\n", ans[i].id,ans[i].p);
}
int m;
int id[maxn],cnt;
vector<node> dfs(int rt){
if((rt<<1)>m){
++cnt;
vector<node> a;a.clear();
a.push_back(node(cnt,1));
return a;
}
vector<node>lc = dfs(rt<<1);
vector<node>rc = dfs(rt<<1|1);
int Llen = lc.size(),Rlen = rc.size();
vector<node>ans;
ans.clear();
for(int i=0;i<Llen;i++){
double sum = 0;
int u = lc[i].id;
// printf("u = %d\n", u);
for(int j=0;j<Rlen;j++){
int v = rc[j].id;
sum += 1.0*a[u]/(1.0*(a[u]+a[v]))*lc[i].p*rc[j].p;
}
ans.push_back(node(u,sum));
}
for(int i=0;i<Rlen;i++){
double sum = 0;
int u = rc[i].id;
for(int j=0;j<Llen;j++){
int v = lc[j].id;
sum += 1.0*a[u]/(1.0*(a[u]+a[v]))*rc[i].p*lc[j].p;
}
ans.push_back(node(u,sum));
}
// printf("rt = %d\n", rt);
// print(ans);
return ans;
}
vector<node>ans;
bool cmp(int a,int b){
return a>b;
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[n-i+1]);
sort(a+1,a+n,cmp);
m = 2*n - 1;
ans = dfs(1);
int len = ans.size();
for(int i=0;i<len;i++){
if(ans[i].id==n){
printf("%.10f\n", ans[i].p);
}
}
return 0;
}