1 条题解

  • 0
    @ 2025-4-7 21:08:21

    题目分析

    这是一个典型的纸牌游戏模拟问题,需要模拟"傻瓜"游戏的出牌过程,并找出先手玩家的最佳首攻策略。

    "傻瓜"是一种使用36张牌(9个等级×4种花色)的双人纸牌游戏:

    牌面等级(从低到高):6、7、8、9、0(代表10)、J(杰克)、Q(王后)、K(国王)、A(王牌)

    花色(优先级从低到高):h(红心)、s(黑桃)、d(方块)、c(梅花)

    其中一个花色被指定为"将牌",具有特殊压制能力

    游戏规则详解

    牌力比较机制

    同花色比较:当两张牌花色相同时,等级高的牌可以压制等级低的牌

    将牌特权:任何将牌都可以压制非将牌,无论等级高低

    非将牌之间不同花色不能互相压制

    完整出牌流程

    (1) 先手玩家(攻击方)选择一张牌打出 (2) 后手玩家(防守方)必须:

    • 选择一张符合压制规则的牌进行防御
    • 若无法压制,则必须收下桌上所有牌 (3) 若防御成功,攻击方可以:
    • 追加打出与桌上任意牌同等级的牌(称为"跟牌")
    • 选择不跟牌,结束本轮 (4) 防守方必须对新跟牌继续防御 (5) 该过程持续,直到:
    • 防守方无法完成防御而收牌
    • 攻击方选择不再跟牌

    胜负判定

    成功迫使防守方收牌的一方获得优势

    未能迫使收牌则视为防守成功

    解题思路

    1. 数据结构设计

      • 使用结构体表示卡牌(等级+花色)
      • 使用集合来管理玩家手牌
    2. 核心算法

      • 压制判断函数:判断一张牌能否压制另一张牌
      • 递归模拟函数:模拟完整的出牌流程
      • 最优选择策略:按等级和花色优先级选择最佳首攻
    3. 优化考虑

      • 提前终止不可能的分支
      • 缓存中间结果提高效率

    完整代码实现

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <string>
    #include <set>
    
    using namespace std;
    
    struct Card {
    	char rank;
    	char suit;
    	
    	bool operator<(const Card& other) const {
    		if (rank != other.rank) return rank < other.rank;
    		return suit < other.suit;
    	}
    };
    
    char trump;
    set<Card> player1, player2;
    
    bool canBeat(const Card& attack, const Card& defense) {
    	if (defense.suit == trump && attack.suit != trump) return true;
    	if (defense.suit == attack.suit && defense.rank > attack.rank) return true;
    	return false;
    }
    
    bool simulate(set<Card> p1, set<Card> p2, const Card& firstAttack) {
    	vector<Card> table;
    	p1.erase(firstAttack);
    	table.push_back(firstAttack);
    	
    	bool attackerTurn = false; // false means player1 is attacking
    	
    	while (true) {
    		bool allBeaten = true;
    		for (const Card& card : table) {
    			bool beaten = false;
    			for (const Card& defense : p2) {
    				if (canBeat(card, defense)) {
    					p2.erase(defense);
    					table.push_back(defense);
    					beaten = true;
    					break;
    				}
    			}
    			if (!beaten) {
    				allBeaten = false;
    				break;
    			}
    		}
    		
    		if (!allBeaten) return true;
    		
    		bool added = false;
    		for (auto it = p1.begin(); it != p1.end(); ) {
    			bool found = false;
    			for (const Card& card : table) {
    				if (it->rank == card.rank) {
    					Card newAttack = *it;
    					it = p1.erase(it);
    					table.push_back(newAttack);
    					added = true;
    					found = true;
    					break;
    				}
    			}
    			if (found) break;
    			else ++it;
    		}
    		
    		if (!added) return false;
    	}
    }
    
    int main() {
    	cin >> trump;
    	string s1, s2;
    	cin >> s1 >> s2;
    	
    	for (int i = 0; i < s1.size(); i += 2) {
    		player1.insert({s1[i], s1[i+1]});
    	}
    	for (int i = 0; i < s2.size(); i += 2) {
    		player2.insert({s2[i], s2[i+1]});
    	}
    	
    	vector<Card> candidates;
    	for (const Card& card : player1) {
    		if (simulate(player1, player2, card)) {
    			candidates.push_back(card);
    		}
    	}
    	
    	if (candidates.empty()) {
    		cout << "NO" << endl;
    	} else {
    		sort(candidates.begin(), candidates.end());
    		cout << candidates[0].rank << candidates[0].suit << endl;
    	}
    	
    	return 0;
    }
    
    
    • 1

    信息

    ID
    1543
    时间
    1000ms
    内存
    64MiB
    难度
    10
    标签
    递交数
    2
    已通过
    0
    上传者