Knockout Tournament 遞迴,暴力求解
阿新 • • 發佈:2020-10-04
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; }