zoj 3983 Crusaders Quest 思维+枚举

题目链接

这道题意思是:

给你一个长度为9的字符串,且只有3个a、3个g、3个o

问,你可以选择删除一段连续的串或者单个的字符也可以不删,最多会出现几个三子相连的子串

比如:agoagoago只有将两种删除完,才能得到三子相连,所以是1

   aaoogggoa,首先里面有一个三子相连(ggg),然后我们删除ggg这三个连续的字符,之后会出现ooo,删除ooo,之后会出现aaa,所以答案是3

 

我们可以分析到:

先检测原串中有几个三子相连,且只会得到0个,1个或者3个,不会有2个

如果原串有一个三子相连,那么最后答案就是2,因为剩下的没有现成三子相连的6个字符删除某些字符只能剩下一个三子相连,且最后一定会剩下一个

如果原串有0个三子相连,那么删除任意个字符后一定会剩下至少一个三子相连,下文续:

想法一:如果里面有一个二子相连(假设为a类字符),并且和另外一个字符中间需要删除的部分中只由一种字符(假设为b类字符)构成,那么我们删除中间的b类字符让二子相连变成三子相连,剩下的另外一种字符一定会通过删完a类字符和b类字符,最后剩下来,又得到一个三子相连

想法二:但是我们不去记录素有二子相连中间与第三子中间的字符种类数,我们选择去枚举每一种字符,分别将它们移除现场,然后检查是否有三子相连,如果有,说明想法一成立,如果分别删除每一种字符都不能形成三子相连,那么说明要达到三子相连必须要删除中间的两种字符,一旦删除两种字符,就不可能有更多的三子相连

 

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;

string str, str2;
char ch[3] = { 'a','g','o' };
const char* _3[3] = { "aaa","ggg","ooo" };

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        int result3 = 0;
        cin >> str;

        auto fun = [&](string& str)
        {
            int re = 3;
            do
            {
                size_t it = 0;
                for (int i = 0; i < 3; ++i)
                    if ((it = str.find(_3[i])) != string::npos)result3++,
                        str.erase(str.begin() + it, str.begin() + it + 3);

            } while (re-- && result3 != 3);
        };

        fun(str);

        if (result3 == 3)
            puts("3");
        else if (result3 == 1)
            puts("2");
        else
        {
            size_t index;
            for (int i = 0; i <= 2; ++i)
            {
                string str2 = str;
                while ((index = str2.find(ch[i])) != string::npos)
                    str2.erase(str2.begin() + index);

                fun(str2);
                if (result3)break;
            }
            if (result3)puts("2");
            else puts("1");
        }
    }
}

 

感谢阅读,生活愉快~

原文地址:https://www.cnblogs.com/lv-anchoret/p/9840764.html