1. 程式人生 > 實用技巧 >Knockout Tournament 遞迴,暴力求解

Knockout Tournament 遞迴,暴力求解

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;
}