P4816 High Card Low Card G题解
P4816 High Card Low Card G题解
思想:贪心
题意简述
给你
解题思路
可以发现此题是类似于一个田忌赛马的游戏,尽量出比对面的牌略大的牌,若找不到则出最小的牌。进一步思考,由于前半局需要出牌点数尽可能大,后半句需要尽可能小,故可以贪心地考虑把玩家的牌按照大小分成前后两个相同的部分,分别用于玩一、二两个部分。由于两个部分是互相独立的,所以可以把对手的纸牌也分成两部分。
把对手的纸牌排序,第一部分的牌从大到小排序,第二部分的牌从小到大排序。容易可以用一个双端队列维护自己的牌,第一部分时查看是否可以让队首的牌战胜对手当前的牌,若可以,则该牌从队首出队;第二部分时从队尾出队
由于玩家的牌和对手的牌总数相同,所以,在把此问题转化为田忌赛马后,可以不用考虑当无法与对手的牌抗衡时出小牌的情况,直接跳过该牌即可。
在处理方面,由于出现的数字上下界比较小,可以使用桶来记录牌是否出现,又由于牌的点数不会重复,考虑到常数的问题,笔者使用了 bitset 充当桶。用桶记录有另一个好处,就是取出后的序列自动有序,不需要重新进行排序。
代码
#include<cstdio>
#include<bitset>
#include<algorithm>
using namespace std;
const int N=50005;
int a1[N],n,a2[N],b[N];
bitset<N<<1> t;
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n>>1;i++)
scanf("%d",&a1[i]),t[a1[i]]=1;
for(int i=1;i<=n>>1;i++)
scanf("%d",&a2[i]),t[a2[i]]=1;
int bn=0;
for(int i=1;i<=n<<1;i++)
if(!t[i])
b[++bn]=i;
sort(a1+1,a1+(n>>1)+1,cmp);
sort(a2+1,a2+(n>>1)+1);
int st=1,tl=bn,ans=0;
for(int i=1;i<=(n>>1);i++)
if(b[tl]>a1[i])
tl--,ans++;
for(int i=1;i<=(n>>1);i++)
if(b[st]<a2[i])
st++,ans++;
printf("%d\n",ans);
}
如果觉得有帮助,点一个免费的赞可以么?