华为OD机试真题 C++ 实现【整理扑克牌】

题目

给定一组数字,表示扑克牌的牌面数字,忽略扑克牌的花色,请按如下规则对这一组扑克牌进行整理:

步骤1、对扑克牌进行分组,形成组合牌,规则如下:当牌面数字相同张数大于等于4时,组合牌为“炸弹”:3张相同牌面数字 + 2张相同牌面数字,且3张牌与2张牌不相同时,组合牌为“葫芦”
3张相同牌面数字,组合牌为“三张”
2张相同牌面数字,组合牌为“对子”
剩余没有相同的牌,则为“单张”:
步骤2、对上述组合牌进行由大到小排列,规则如下:不同类型组合牌之间由大到小排列规则:“炸弹” >"葫芦”>"三张”>"对子”> “单张”:相同类型组合牌之间,除“葫芦”外,按组合牌全部牌面数字加总由大到小排列:"葫芦”则先按3张相同牌面数字加总由大到小排列,3张相同牌面数字加总相同时,再按另外2张牌面数字加总由大到小排列;
由于“葫芦”>“三张”,因此如果能形成更大的组合牌,也可以将“三张”拆分为2张和1张,其中的2张可以和其它“三张”重新组合成“葫芦”,剩下的1张为“单张”

步骤3、当存在多个可能组合方案时,按如下规则排序取最大的一个组合方案:依次对组合方案中的组合牌进行大小比较,规则同上:当组合方案A中的第n个组合牌大于组合方案B中的第n个组合牌时,组合方案A大于组合方案B;
输入描述:
第一行为空格分隔的N个正整数,每个整数取值范围[1,13],N的取值范围[1,1000]

输出描述:
经重新排列后的扑克牌数字列表,每个数字以空格分隔

示例1
输入:
1 3 3 3 2 1 5
输出:
3 3 3 1 1 5 2
示例2
输入:
4 4 2 1 2 1 3 3 3 4
输出:
4 4 4 3 3 2 2 1 1 3

思路

1:逻辑 排序

#include<bits/stdc++>

using namespace std;

bool cmp(pair<int, int> x, pair<int, int> y) {
    if (x.second == y.second) {
        return y.first<x.first;
    } else {
        return y.second < x.second;
    }
}
 
int main()
{
    //输入处理
    int tmp;
    vector<int> nums;
    while(cin >> tmp) {
        nums.push_back(tmp);
        if(cin.get() == '\n') {
            break;
        }
    }
    
    //key为牌面点数,value为该点数的张数
    map<int, int> card;
    for (int i=0;i<nums.size();i++) {
        if (card.count(nums[i])) {
            card[nums[i]] += 1;
        } else {
            card[nums[i]] = 1;
        }   
    }
 
    //把map中元素转存到vector中   
    vector<pair<int, int>> card_vec(card.begin(),card.end());
    //排序,先按张数排序,再按点数排序
    sort(card_vec.begin(), card_vec.end(), cmp); 
 
    // 特殊情况处理
    string result = "";
    vector<int> split_cards;  
    for(int i=0; i<card_vec.size(); i++){
        pair<int, int> temp = card_vec[i];
        int carNum = temp.first;
        int carCount = temp.second;
        // 3+3的情况,要拆分成葫芦
        if(i > 0 && card_vec[i-1].second == 3 && carCount == 3){
            split_cards.push_back(carNum);
            carCount = 2;
            temp.second = 2;
        // 给拆分的牌也组合一下
        }else if(carCount == 1 && split_cards.size() != 0){ 
            for (int k=0; k<split_cards.size(); k++){
                // 当拆分中的牌大于此牌时,先安排拆分的牌
                if(split_cards[k] > carNum){    
                    result += to_string(split_cards[k]) + " ";
                    split_cards.erase(split_cards.begin() + k); 
                    k--;   
                }
            }
        }
        for(int j=0; j<carCount; j++){
            result += to_string(carNum) + " ";
        }
    }
 
    if(split_cards.size() != 0){
        for(int i : split_cards){
            result += to_string(i) + " ";
        }
    }
 
    cout << result;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值