xmuoj.宁宁与塔罗牌

描述

魔女宁宁有很多套占卜用的塔罗牌(这里为了方便表示,使用1~78的整数表示不同的塔罗牌牌面)。某天,部分塔罗牌在魔法的作用下两两结合,形成了双面塔罗牌。宁宁数了数,这些双面塔罗牌一共有 N 张,每张牌的牌面信息如下:第 i 张双面塔罗牌的正面为 A_i,反面为 B_i(都是1~78的整数)。宁宁想要好好利用这些无法再拿来占卜的双面塔罗牌,于是她想到了一个可以用这些牌来玩的博弈游戏,游戏规则如下。

最初,这 N 张双面塔罗牌平铺在桌面上,有两名玩家轮流进行操作(所有牌面信息都是已知的):从桌面上选择一对牌,要求它们正面相同或者反面相同,然后从桌面上移除这两张牌。如果不存在这样的牌对,则当前玩家输掉游戏,另一名玩家获胜。

宁宁邀请你来玩这个博弈游戏。现在你作为先手,想知道在双方都采取最优策略的情况下,你是否能够赢下游戏。

出题者为刘之流同学

输入

第 1 行一个整数 N (1<=N<=18)。

接下来是 N 行描述牌面信息的数据,每行两个整数 A_i 和 B_i (1<=A_i,B_i<=78)。

输出

若在双方都采取最优策略的情况下,你能够赢下游戏,则输出"YES",否则输出"NO"。

#include <iostream>
#include <vector>
#include <unordered_map>

using namespace std;

unordered_map<int, bool> memo;

bool canWin(vector<pair<int, int>>& cards, int usedMask) {
    int n = cards.size();

    if (memo.find(usedMask) != memo.end()) {
        return memo[usedMask];
    }

    for (int i = 0; i < n; ++i) {
        if (usedMask & (1 << i)) continue;
        for (int j = i + 1; j < n; ++j) {
            if (usedMask & (1 << j)) continue;
            if (cards[i].first == cards[j].first || cards[i].second == cards[j].second) {
                int newMask = usedMask | (1 << i) | (1 << j);
                if (!canWin(cards, newMask)) {
                    memo[usedMask] = true;
                    return true;
                }
            }
        }
    }

    memo[usedMask] = false;
    return false;
}

int main() {
    int n;
    cin >> n;

    vector<pair<int, int>> cards(n);
    for (int i = 0; i < n; ++i) {
        cin >> cards[i].first >> cards[i].second;
    }

    int initialMask = 0;
    if (canWin(cards, initialMask)) {
        cout << "YES" << endl;
    } else {
        cout << "NO" << endl;
    }

    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值