1671.扑克牌

信息学奥赛一本通 贪心算法

【题目描述】


一副扑克牌有n张普通牌加一张特殊牌
现在n种牌各有a1 , a2 , … , an张,还有 b bb 张特殊牌
一副牌可以由n种普通牌各一张组成,也可以由n−1种普通牌各一张再加一张特殊牌组成
输出最多能整理出的牌的副数。

【输入】


第一行给出n和b。
第二行给出a1,a2,…,an。

【输出】


输出最多能整理出的牌的副数。

【数据】


对于20%的数据,1≤n≤100,牌的数量小于100。
对于40%的数据,1≤n≤3000。
对于100%的数据,1≤n≤1000000,牌的数量 ≤10^{6}
时间限制: 1000ms
内存限制: 262144KB

【输入样例】

5 5
5 5 5 5 5

【输出样例】

6

【分析】

题目描述不是太好理解,现在对样例数据进行一个解读。5种牌分别各有5张,就以1、2、3、4、5来表示,即1有5张,2有5张……那么答案的6副牌是什么样的呢,我用表格来表示,每一行表示一副牌,其中T表示特殊牌。

T2345
1T345
12T45
123T5
1234T
12345

补充一个样例:

5 5

5 1 2 3 4

答案:3

也是五种牌,每种牌的数量不相同了,需要先对牌的数量进行一个排序,表格中上面三行对应答案的3副牌。

T2345
T2345
1T345
45
5

题目适用于贪心来解题,调整几种牌中数量最小的那个。补充样例中,不使用特殊牌,只能凑出1副牌(1,2,3,4,5),将特殊牌补充到1里,可以凑出2副牌(T,2,3,4,5 / 1,2,3,4,5),再将特殊牌补充到1、2各一个,可以凑出3副牌,如上面表格所示。那么可以继续添加特殊牌吗?再添加一个T到1、2、3中一列,还有两个空无法填充,即用了4个特殊牌也只能凑出3副牌。

补充特殊牌退出条件有两个:

1、使用特殊牌的数量大于能凑出的牌数,即大于队列中最小的那个数,如补充例子里展示的那样

2、特殊牌用完了

#include<bits/stdc++.h>
using namespace std;
int n,b;
//优先队列
priority_queue <int, vector<int>,greater<int>> q;
int ans;
int main() {
    cin>>n>>b;
    for(int i=1;i<=n;i++){//优先队列保存n张牌
        int a;
        cin>>a;
        q.push(a);
    }
    ans=q.top();//记录最初可以凑出的牌数
    for(int i=1;i<=b;i++){//将特殊牌补充到队列里
        int t = q.top();
        q.pop();
        t++;//加到最少的那种牌里
        q.push(t);//补充后放回队列
        ans=q.top();//当前最少的牌数,即当前可凑出的牌数
        if (i>ans){//如果使用的特殊牌超过了整副牌数量,表示无法再凑出更多的牌数了
            break;
        }
    }
    cout<<ans;//输出答案
    //cout << q.top()
    return 0;
}

### 创建扑克牌游戏的Python教程 #### 定义卡片类 `Card` 为了构建一个完整的扑克牌游戏,定义一个`Card` 类用于表示单张扑克牌。每一张卡具有两个属性:点数 (`points`) 和花色 (`suits`)。 ```python class Card(): # 扑克牌类初始化方法 def __init__(self, point, suit): self.point = point # 卡片点数 self.suit = suit # 花色 def __repr__(self): return f"{self.point}{self.suit}" ``` 此部分代码展示了如何创建一个简单的扑克牌对象[^1]。 #### 构建一副标准扑克牌 通过循环遍历所有可能的组合来生成一整副扑克牌: ```python import itertools class Deck: points = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'] suits = ['♠', '♥', '♣', '♦'] def __init__(self): self.cards = [Card(point, suit) for point, suit in itertools.product(Deck.points, Deck.suits)] def shuffle(self): import random random.shuffle(self.cards) def deal_card(self): return self.cards.pop() if self.cards else None ``` 上述代码实现了扑克牌组(`Deck`) 的建立、洗牌以及发牌功能[^3]。 #### 发牌逻辑 当玩家加入游戏时,则可以从已经准备好的牌堆中抽取指定数量的手牌给每位参与者: ```python def deal_hands(deck, num_players, hand_size=5): hands = [[] for _ in range(num_players)] for i in range(hand_size * num_players): player_index = i % num_players card = deck.deal_card() if not card: break hands[player_index].append(card) return hands ``` 这段函数负责按照设定的人数和手牌大小分配初始手牌[^2]。 #### 游戏流程控制 最后一步是设置整个游戏的过程框架,在这里可以添加更多具体的游戏规则或者互动环节: ```python if __name__ == "__main__": players_count = int(input("请输入参与人数: ")) my_deck = Deck() print("\n正在洗牌...") my_deck.shuffle() print(f"\n向{players_count}位玩家各分发五张牌:") distributed_cards = deal_hands(my_deck, players_count) for idx, hand in enumerate(distributed_cards, start=1): print(f"玩家 {idx}: {[str(c) for c in hand]}") ``` 以上就是使用 Python 编写基本版多人纸牌游戏的主要步骤。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值