uva 10128 Queue 递归+排列组合

这周的专题是回溯,而我这题的解法是排列组合,思路其实是DP的思维,考虑到N个人的排列中最高的那个人可能站的位置,把整个排列分成两个部分,要使整个排列从前往后看是p个人,递归的解决前半部分从前往后看是p-1个人的子问题,问题存在最优子结构和重复计算的性质,肯定可以用动态规划自底向上解决,考虑到数据的范围较小,所以用递归没有问题。特别要注意的是这里的前半部分要用有C(n-1,i)种选择,对于后半部分可以任意组合所以有A(n-i-1)种组合,特别懵逼的是自己做的D题,一个劲的交C题,然后拼命找WA的原因的状态,真的…一言难尽!

/*代码没注释,回看两行泪*/
LL A(LL n){
	if(n<=1)
	return 1;
	return n*A(n-1);
}
LL C(LL m,LL n){
	return A(m)/A(n)/A(m-n);
}
//解决n个位置,从前往后或从后往前看 能看到p个人的子问题 
//从后往前看和从前往后是对称的 
LL solve(LL n,LL p){
	if(n<p)	return 0;//不可能 
	if(n==p) return 1;
	LL ans=0;
	for(int i=0;i<n;i++){//i代表把最高的人置于这个位置 
		ans+=C(n-1,i)*solve(i,p-1)*A(n-i-1);
	}
	return ans;
}

int main()
{  
   int t;cin>>t;
   while(t--){
    int n,p,r;
   	cin>>n>>p>>r;
   	LL ans=0;
   	for(int i=0;i<n;i++){//i代表把最高的人置于这个位置
   		ans+=C(n-1,i)*solve(i,p-1)*solve(n-i-1,r-1);
	   }
	   cout<<ans<<endl;
   }
   return 0;	
}

猜你喜欢

转载自blog.csdn.net/Csdn_jey/article/details/90441191
今日推荐