Ban or Pick, What‘s the Trick

文章讲述了在Dota2竞赛中,两个队伍如何通过交替进行英雄禁选操作来最大化或最小化他们的战争团战得分。玩家Bob想知道在双方都采取最优策略时,最终的得分差。文章介绍了一个动态规划方法来计算这个问题的解决方案。

Bobo has recently learned how to play Dota2. In Dota2 competitions, the mechanism of banning/picking heroes is introduced, modified and simplified as follows for the sake of the problem:

Suppose a game is played between two teams: Team A and Team B. Each team has a hero pool of nn heroes with positive utility scores a_1,\dots,a_na1​,…,an​ and b_1,\dots,b_nb1​,…,bn​, respectively. Here we assume all heroes in two teams' hero pool are distinct.

The two teams then perform ban/pick operations alternately, with Team A going first. In one team's turn, it can either pick a hero for itself, or ban an unselected hero from the opponent's hero pool.

After 2n2n turns, all heroes are either picked or banned. Each team then needs to choose at most kk heroes from all heroes it picked to form a warband and the score for the warband is calculated as the sum of utility scores over all heroes in it.

Let s_A, s_BsA​,sB​ be the score of the warband formed by Team A and Team B, respectively. Team A wants to maximize the value of s_A-s_BsA​−sB​ while Team B wants to minimize it.

Bobo wants to know, what should be the final value of s_A-s_BsA​−sB​, if both teams act optimally? He's not really good at calculating this, so he turned to you for help.

An example of banning/picking heroes in Dota2. Source: TI10 True Sight

Input

The first line contains two integers n,k(1\leq n\leq 10^5,1\leq k \leq 10)n,k(1≤n≤105,1≤k≤10).

The second line contains nn integers a_1,a_2,\dots,a_na1​,a2​,…,an​ (1\leq a_i\leq 10^8)(1≤ai​≤108), denoting the utility score of heroes for Team A.

The third line contains nn integers b_1,b_2,\dots,b_nb1​,b2​,…,bn​ (1\leq b_i\leq 10^8)(1≤bi​≤108), denoting the utility score of heroes for Team B.

Output

Output an integer in one line, denoting the answer.

Sample 1

InputcopyOutputcopy
2 1
3 6
2 4
2

Sample 2

InputcopyOutputcopy
4 1
1 3 5 7
2 4 6 8
0

Sample 3

InputcopyOutputcopy
4 2
4 6 7 9
2 5 8 10
3
#include<iostream>
#include<algorithm>
#include<map>
#include<cstring>
#include<vector>

using namespace std;
typedef long long ll;
const ll INF = 0x3f3f3f3f3f3f3f;
const int N = 1e5 + 10;
const int K = 11;

int n, k;
int a[N], b[N];
ll dp[2 * N][K][K];//双方操作总和,a选的英雄,b选的英雄
//dp记录sa-sb
int vis[2 * N][K][K];

bool cmp(int a, int b)
{
	return a > b;//从大到小排序
}

ll find(int s, int na, int nb)//s表示当前轮次进行了多少次操作,na表示A选择了几个英雄,nb表示B选择了几个英雄
{
	//如果已经处理完所有的轮次,则返回0
	if (s > 2 * n) return 0;

	//如果之前已经计算过这个状态,则直接返回之前计算得到的结果
	if (vis[s][na][nb]) return dp[s][na][nb];
	vis[s][na][nb] = 1;

	//根据当前状态计算出A、B分别选择哪个英雄
	int ta = s / 2 - nb + na;
	int tb = (s + 1) / 2 - na + nb;

	//在奇数轮中,A先选择一个英雄,然后B再选择一个英雄
	if (s & 1)
	{
		int ta = ((s - 1) / 2 - nb) + na + 1;
		//在当前状态下,A不选择这个英雄
		dp[s][na][nb] = find(s + 1, na, nb);
		//如果A还没有选择k个英雄,并且ta小于等于n,则考虑选择这个英雄
		if (ta <= n && na < k) dp[s][na][nb] = max(dp[s][na][nb], find(s + 1, na + 1, nb) + a[ta]);
		return dp[s][na][nb];
	}

	//在偶数轮中,B先选择一个英雄,然后A再选择一个英雄
	else
	{
		int tb = (s / 2 - na) + nb + 1;
		//在当前状态下,B不选择这个英雄
		dp[s][na][nb] = find(s + 1, na, nb);
		//如果B还没有选择k个英雄,并且tb小于等于n,则考虑选择这个英雄
		if (tb <= n && nb < k) dp[s][na][nb] = min(dp[s][na][nb], find(s + 1, na, nb + 1) - b[tb]);
		return dp[s][na][nb];
	}
}

int main()
{
	memset(dp, -1, sizeof dp);//初始化dp数组为-1

	scanf("%d %d", &n, &k);

	for (int i = 1; i <= n; i++) scanf("%d", &a[i]); sort(a + 1, a + n + 1, greater<int>());//从大到小排序
	for (int i = 1; i <= n; i++) scanf("%d", &b[i]); sort(b + 1, b + n + 1, greater<int>());

	//从状态(1,0,0)开始计算
	find(1, 0, 0);

	cout << dp[1][0][0] << endl;//输出最终的结果

}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值