CF1056C Pick Heroes 题解

CF1056C Pick Heroes 题解

题面翻译

交互题。

2 n 2n 2n 位英雄,第 i i i 位英雄的战力为 p i p_i pi,你和交互库轮流选择英雄组成队伍, t = 1 t=1 t=1 时你先手, t = 2 t=2 t=2 时交互库先手。

英雄之间存在 m m m 对仇敌 a i , b i a_i,b_i ai,bi(保证每位英雄至多只出现一次),一旦一位玩家选择了第 a i a_i ai 位英雄,那么另一位玩家必须 立即 选择第 b i b_i bi 位英雄;同理,一位玩家选择了第 b i b_i bi 位英雄,那么另一位玩家必须立即选择第 a i a_i ai 位英雄。

队伍的总战力即为队伍内所有英雄战力之和。

尝试找到最佳策略,最大化你队伍的总战力。

注意交互库不一定选择最优策略,但你的选择必须是当前最优的方案(即在交互库也使用最优策略的情况下,你的方案是最优的)

数据范围: 1 ≤ n ≤ 1 0 3 , 0 ≤ m ≤ n , 1 ≤ p i ≤ 1 0 3 , 1 ≤ a i , b i ≤ 2 n , a i ≠ b i 1\le n\le 10^3,0\le m \le n,1\le p_i \le 10^3,1\le a_i,b_i \le 2n,a_i \not= b_i 1n103,0mn,1pi103,1ai,bi2n,ai=bi

题目描述

Don’t you tell me what you think that I can be

If you say that Arkady is a bit old-fashioned playing checkers, you won’t be right. There is also a modern computer game Arkady and his friends are keen on. We won’t discuss its rules, the only feature important to this problem is that each player has to pick a distinct hero in the beginning of the game.

There are 2 2 2 teams each having n n n players and 2 n 2n 2n heroes to distribute between the teams. The teams take turns picking heroes: at first, the first team chooses a hero in its team, after that the second team chooses a hero and so on. Note that after a hero is chosen it becomes unavailable to both teams.

The friends estimate the power of the i i i -th of the heroes as p i p_i pi . Each team wants to maximize the total power of its heroes. However, there is one exception: there are m m m pairs of heroes that are especially strong against each other, so when any team chooses a hero from such a pair, the other team must choose the other one on its turn. Each hero is in at most one such pair.

This is an interactive problem. You are to write a program that will optimally choose the heroes for one team, while the jury’s program will play for the other team. Note that the jury’s program may behave inefficiently, in this case you have to take the opportunity and still maximize the total power of your team. Formally, if you ever have chance to reach the total power of q q q or greater regardless of jury’s program choices, you must get q q q or greater to pass a test.

输入格式

The first line contains two integers n n n and m m m ( 1 ≤ n ≤ 1 0 3 1 \le n \le 10^3 1n103 , 0 ≤ m ≤ n 0 \le m \le n 0mn ) — the number of players in one team and the number of special pairs of heroes.

The second line contains 2 n 2n 2n integers p 1 , p 2 , … , p 2 n p_1, p_2, \ldots, p_{2n} p1,p2,,p2n ( 1 ≤ p i ≤ 1 0 3 1 \le p_i \le 10^3 1pi103 ) — the powers of the heroes.

Each of the next m m m lines contains two integer a a a and b b b ( 1 ≤ a , b ≤ 2 n 1 \le a, b \le 2n 1a,b2n , a ≠ b a \ne b a=b ) — a pair of heroes that are especially strong against each other. It is guaranteed that each hero appears at most once in this list.

The next line contains a single integer t t t ( 1 ≤ t ≤ 2 1 \le t \le 2 1t2 ) — the team you are to play for. If t = 1 t = 1 t=1 , the first turn is yours, otherwise you have the second turn.

Hacks

In order to hack, use the format described above with one additional line. In this line output 2 n 2n 2n distinct integers from 1 1 1 to 2 n 2n 2n — the priority order for the jury’s team. The jury’s team will on each turn select the first possible hero from this list. Here possible means that it is not yet taken and does not contradict the rules about special pair of heroes.

输出格式

When it is your turn, print a single integer x x x ( 1 ≤ x ≤ 2 n 1 \le x \le 2n 1x2n ) — the index of the hero chosen by you. Note that you can’t choose a hero previously chosen by either you of the other player, and you must follow the rules about special pairs of heroes.

When it is the other team’s turn, read a line containing a single integer x x x ( 1 ≤ x ≤ 2 n 1 \le x \le 2n 1x2n ) — the index of the hero chosen by the other team. It is guaranteed that this index is not chosen before and that the other team also follows the rules about special pairs of heroes.

After the last turn you should terminate without printing anything.

After printing your choice do not forget to output end of line and flush the output. Otherwise you will get Idleness limit exceeded. To do this, use:

  • fflush(stdout) or cout.flush() in C++;
  • System.out.flush() in Java;
  • flush(output) in Pascal;
  • stdout.flush() in Python;
  • see documentation for other languages.

Jury’s answer − 1 -1 1 instead of a valid choice means that you made an invalid turn. Exit immediately after receiving − 1 -1 1 and you will see Wrong answer verdict. Otherwise you can get an arbitrary verdict because your solution will continue to read from a closed stream.

样例 #1

样例输入 #1

3 1
1 2 3 4 5 6
2 6
1

2

4

1

样例输出 #1

6

5

3

样例 #2

样例输入 #2

3 1
1 2 3 4 5 6
1 5
2
6

1

3

样例输出 #2

5

4

2

提示

In the first example the first turn is yours. In example, you choose 6 6 6 , the other team is forced to reply with 2 2 2 . You choose 5 5 5 , the other team chooses 4 4 4 . Finally, you choose 3 3 3 and the other team choose 1 1 1 .

In the second example you have the second turn. The other team chooses 6 6 6 , you choose 5 5 5 , forcing the other team to choose 1 1 1 . Now you choose 4 4 4 , the other team chooses 3 3 3 and you choose 2 2 2 .

引入:

洛谷题解中要么代码没放,要么代码很长很繁琐。因此我来交一发代码量只有 1008 B 1008 B 1008B 的题解。

算法:贪心

考虑这种 博弈题 常用的思考方式:分类讨论 先后手

先手:

注意到题目中说每对仇敌必须一起选。因为我们要保留先手的优势,所以我们应当先选择每对英雄中 战斗力最强的

之后,再选择剩余英雄中 战斗力最强的 即可。

后手:

如果交互库选择了仇敌中的一个,那么只能选与之相匹配的英雄。

否则,我们就获得了先手,之后便和先手策略一致了。

数据结构:

因为我们要维护战斗力最强的英雄,所以可以用 set 或者 priority_queue 。这里我选择了 set,因为 set 可以很方便地删除其中的任意元素。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=2e3+10;
ll n,m,op,t,c,a[N],b[N],p[N],l[N],x[N];
bool vis[N];
multiset<pair<ll,ll> > q; 
void first(){
	for(int i=1;i<=m;i++)
		if(!vis[i]){
			cout<<(p[a[i]]>p[b[i]]?a[i]:b[i])<<"\n";
    		fflush(stdout); 
    		cin>>t;
    		q.erase({-p[a[i]],a[i]});
    		q.erase({-p[b[i]],b[i]});
		}	
	while(!q.empty()){
		cout<<(*q.begin()).second<<"\n";
		q.erase(q.begin());
		fflush(stdout); 
		if(!q.empty()){cin>>t;q.erase({-p[t],t});}		
	}
}
int main(){
    cin>>n>>m;c=m;
    for(int i=1;i<=n*2;i++) cin>>p[i],q.insert({-p[i],i});
    for(int i=1;i<=m;i++) cin>>a[i]>>b[i],l[a[i]]=b[i],l[b[i]]=a[i],x[a[i]]=x[b[i]]=i;
    cin>>op;
    if(op==1) first();
	else
		for(int i=1;i<=n;i++){
			cin>>t;
			q.erase({-p[t],t});
			if(l[t]&&q.find({-p[l[t]],l[t]})!=q.end()){
				cout<<l[t]<<"\n";
				fflush(stdout); 
				q.erase({-p[l[t]],l[t]});vis[x[t]]=1;
			}else{first();break;}
		}
	return 0;
}

代码很短,只有 41 41 41 行。

怎么样?点个赞再走吧~

  • 35
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值