AI刷题第159题:小C的回文博弈 (数学分类讨论)| 豆包MarsCode AI刷题

53 阅读3分钟

1、题目原文

问题描述

小C和小U在一场激烈的回文博弈中展开对决。游戏从一个初始字符串s开始,规则如下:

  1. 每个玩家轮流行动,每次行动都可以重新排列字符串。
  2. 如果通过重新排列能够形成一个回文串,游戏立即结束,当前玩家获胜。
  3. 如果无法形成回文串,玩家必须删除字符串中的一个字符,游戏继续。

小C总是先手,两人都使用最优策略,最终谁将赢得这场比赛呢?如果小C获胜则输出"C",小U获胜则输出"U"


测试样例

样例1:

输入:s = "aab"

输出:'C'

样例2:

输入:s = "abc"

输出:'C'

样例3:

输入:s = "abcd"

输出:'U'

2、解题思路

想要构建一个回文字符串,比较关键的内容就是字符的数量的奇偶性,更具体来说,是数量为奇数的字符和数量为偶数的字符串。更进一步,可以分为奇数字符的数量的奇偶性(比如有3或4个数量为奇数的字符)和偶数字符的数量(比如有3或4个数量为偶数的字符)。

这道题可以理解为一种数学上的分情况讨论的题。

问题1:偶数的个数是否重要

举例来说,在一个字符串中,某几个数量为偶数的字符的具体数目为 2,2,2 或者2,2,2,2。对于这道题来说有没有区别呢?

答案是没有区别。我们假设B在修改偶数字符前处于优势地位(也就是可以取得最终的胜利),那么当A尝试去修改偶数字符,将其转换为奇数字符,(2,2,2,2 → 2,2,2,1)从而改变自己的获胜情况时,B可以立刻再对该偶数字符进行一次修改,从而继续维护自己的优势地位。(2,2,2,1→ 2,2,2,0),也就是说,对于参与操作的双方来说,无论偶数的数量是奇数还是偶数,都无法影响最终的结果,所以我们在进行统计的时候实际上就可以不用管这一部分的内容了。

问题2:奇数的个数是否重要

很重要,如果想要获胜,实际上就是最先将奇数的个数降为1或者0;

如果初始化时,奇数的个数就为0或者1,那么先发者直接就获得了胜利。

如果奇数的个数为奇数,那么在不断的将奇数转变为偶数的过程中,先发者最终会先达到奇数数量为1的情况,从而获得胜利。

如果奇数的个数为偶数,先发者在进行任意操作之后,就转换到了上面的情况,从而输掉比赛。

具体代码:

简单来说就是先统计奇数和偶数的字符,然后再统计奇数的个数,从而直接得到胜利者。

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

using namespace std;

char solution(const std::string& s) {
    // write code here
    unordered_map<char,int > m;
    for(int i=0;i<s.length();++i){
        m[s[i]]++;
    }
    int countOdd = 0;
    for(auto it:m){
        if(it.second%2){
            countOdd++;
        }
    }
    char ans=' ';
    if(countOdd==0 || countOdd ==1 || countOdd%2 ){
        ans='C';
    }
    else{
        ans='U';
    }

    return ans;
}

int main() {
    std::cout << (solution("aab") == 'C') << std::endl;
    std::cout << (solution("abc") == 'C') << std::endl;
    std::cout << (solution("abcd") == 'U') << std::endl;
    return 0;
}