# 游戏预言
## 题目描述
John 和朋友们在玩纸牌游戏,他们一共有 $m$ 个人(包括 John)。他们的纸牌比较特殊,一共有 $n \times m$ 张牌,牌号分别为 $1,2,\dots,n \times m$,没有牌号相同的牌。每个人先拿到 $n$ 张牌,然后,每一轮,每个人出一张牌,谁最大则谁赢得这一轮。现在已知 John 手中的 $n$ 张牌,计算他最少能赢得多少轮。
## 输入格式
第一行为两个整数 $m$ 和 $n$。
第二行有 $n$ 个正整数,表示 John 手中的 $n$ 张牌的数值。
## 输出格式
仅一个整数,表示 John 最少能赢的次数。
## 样例 #1
### 样例输入 #1
```
2 5
1 7 2 10 9
```
### 样例输出 #1
```
2
```
## 样例 #2
### 样例输入 #2
```
6 11
62 63 54 66 65 61 57 56 50 53 48
```
### 样例输出 #2
```
4
```
## 提示
对于 $100 \%$ 的数据,$2 \le m \le 20$,$1 \le n \le 50$。
首先思考一下:
题目要的是John最少赢几局,那么我们代入对方的视角莱想一想:如果你跟John打牌,你怎么让他赢的次数少呢?假设John出了一张5,你手上有一张6,这时候有两种情况:
①不出这张6,让John赢一次,如果John后面的牌全都≥6那么这张6废了
②出这张6,让John输一次,后面John出什么牌只要我有比他大的就压,比他大的牌出完了他就赢一局
那么按照题目意思,要让John输的次数最多
那么代码思路就出来了,双方都从大到小出牌,遇上自己的牌就加入自己的牌堆(cnt++),如果你有牌而且比John最大的牌还大,那就压上(cnt--);如果比John大的牌出完了就是他赢了(cnt<1,也就是比John的牌更大的牌不足一张)
那么我们需要用桶排序,确认我的牌和John的牌的数量,因为我的牌从大到小排列,只要John最大的牌比我的牌小,那么他后面的所有牌都比我小(废话,但是写进代码里很有用)
下面是代码:
#include<iostream> using namespace std; //最多有50张牌,从1开始存,所以数组开到51 int a[51]; //最多有20个人,20*50=1000,防止越界就开到1001 bool b[1001]; int main(){ //cnt记下我比John大的牌的数目 //ans记录john赢的次数 int n,m,cnt=0,ans=0; cin>>n>>m; //桶排序,因为题目说了不会有重复的牌所以不用担心桶排序吞掉牌 for(int i=1;i<=m;i++){ cin>>a[i]; //把John有的牌标记为1 b[a[i]]=1; } //从牌堆最后一张开始往前推,其实就是从大到小出牌的模拟 m*=n; for(int i=m;i>=1;i--){ //如果这张牌是我的,那么放进我的牌堆 //如果上一张是John的,那也被结算了,要么我有比他还大的牌,要么他赢一次 if(b[i]==0){ cnt++; } //如果这张牌是他的,判断我有没有比他大的牌,如果cnt>=1说明我有一张牌比他这张更大 //根据我们的思路,我们要把这张牌出了,也就是cnt-- else if(cnt>=1)cnt--; //如果cnt<1说明我没牌比他大,也就是比他大的牌全出完了,那他就赢了这一局 //ans++ else ans++; } //输出ans cout<<ans; return 0; }
标签:cnt,游戏,##,样例,张牌,P2649,int,预言,John From: https://www.cnblogs.com/Ghost1GM/p/16714039.html