传送门
题意
T和HL两个人玩游戏,游戏规则为:由若干个非空堆,玩家选择一个非空堆,然后从中取出单个石头。但是,一个人不能选择在前一回合中选择的筹码(另一位玩家选择的筹码,或者如果当前回合是第一回合,则玩家可以选择任何非空筹码)。 不能依次选择一堆的玩家输了,游戏结束了。T先开始,两个人都很聪明,都会选择最优策略。 问T和HL谁能赢?
分析
首先我们得确定,在不违反规则的情况下,我们应该选择最大的那一堆石子
因为很明显,如果我选择了最大的一堆石子,那么不管我如何选择,下一轮我任然可以选择这堆石子,而对手选择次大堆的石子的话,下一轮这一堆石子依然是最大的,可以保证一直延续下去。 所以我们用一个优先队列进行维护即可
两种状态 1.T取出一堆石子,然后发现没有剩下的堆,T获胜 2.HL取出一堆石子,然后发现没有剩下的堆,HL获胜
我们可以很轻易的发现,如果HL取完石子,如果队列为空,那么一定HL获胜,因为如果剩下一堆石子,就会是HL取完剩下的那一堆,而这是次大堆,所以肯定还有另一堆石子存在,所以如果HL获胜那么一定就是HL取完之后队列为空才可
代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC option("arch=native","tune=native","no-zero-upper")
#pragma GCC target("avx2")
using namespace std
;
typedef long long ll
;
typedef unsigned long long ull
;
typedef pair
<int,int> PII
;
const int INF
= 0x3f3f3f3f;
const int N
= 110;
int a
[N
];
int n
;
int main(){
int T
;
scanf("%d",&T
);
while(T
--){
priority_queue
<int> Q
;
scanf("%d",&n
);
while(n
--){
int x
;
scanf("%d",&x
);
Q
.push(x
);
}
while(Q
.size()){
int x
= Q
.top();
Q
.pop();
if(Q
.empty()){
puts("T");
break;
}
int y
= Q
.top();
Q
.pop();
if(x
- 1) Q
.push(x
- 1);
if(y
- 1) Q
.push(y
- 1);
if(Q
.empty()){
puts("HL");
break;
}
}
}
return 0;
}