S13瑞士轮中的动态规划

大家好,我是老学长。

最近英雄联盟S13比赛正在如火如荼的进行之中,其中有一个非常有趣的赛制,叫做瑞士轮。
在这里插入图片描述
瑞士轮把16支队伍放在一起比赛。这样必然会生成8支1-0战绩的队伍和8支0-1的队伍。相同战绩的队伍和相同战绩的队伍对战。直到获胜3场晋级或者3场失利淘汰,循环才结束。这样的赛制安排可以保证对局的队伍能够保持近似相同的水平,不会导致碾压式的枯燥对局产生。相近队伍相比会让比赛更有看点。

看到瑞士轮赛制,我头中浮现出一个算法问题。一开始有16支0-0战绩的队伍,现在我想求1-1战绩的队伍,应该怎么求?

从图中我们看出 1-1战绩的队伍是由两个部分组成的,分别是1-0队伍的一半和0-1队伍的一半。

1-0 和 0-1 又分别是 0-0 的一半

通过递归我们可以求出1-1战绩队伍的数量。

那如果我想求a-b战绩的队伍应该怎么办?

我们虽然不能直面求a-b战绩的队伍,但是我们可以得到a-b战绩的队伍应该是由(a-1) - b 战绩队伍的一半 和 a - (b-1) 战绩队伍的一半 获得的。这样我们就可以列出递归表达式。

对于0 - b 和 a - 0 战绩的队伍,由于不可能由负战绩的队伍,所以只有一部分。

递归的出口就是 0 - 0队伍,也就是参加队伍的数量。

这样我们就可以写出递归表达式

代码如下

#include<iostream>
using namespace std;

int dp(int a,int b){
	
	if(a == 0 && b == 0) return 16;
    if(a == 0){
    	return dp(a,b-1) / 2;
	}
	
	if(b == 0){
		return dp(a-1,b) / 2;
	}
	
	

    
	int part_a = dp(a-1,b) / 2;
	int part_b = dp(a,b-1) / 2;
	
	return part_a + part_b; 
	
	
}
int main(){
	cout<<dp(2,1);
	return 0;
}

这种方法就是递归算法,运用到了动态规划的思想。a-b战绩的队伍可以划分成两部分,如果之前我们将两部分算出来储存到数组中,就可以直接进行调用。大大减少了我们的计算量。

真是没想到一个小小的世界赛,居然蕴含了这么巧妙的算法。所以要好好学习数学和算法,要不然说是英雄联盟老玩家,连世界赛的赛制都看不懂就尴尬了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值