牛客网刷题实录

牛客网编程题

  1. 消消看

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 64M,其他语言128M

牛牛和牛妹最近迷上了新版消消看,该游戏规则如下:

在一个 串中,每一轮,玩家都可以选择一串连续相同字符进行消除,消除之后,左右两侧剩余的字符自动拼接,重新形成一个字符串。
例如:在 中,牛牛选择了第四个和第五个字符,它们连续且都是 ,满足消除条件,而当它们消除之后,左侧剩余的 和右侧剩余的 会拼接到一起,即:消除后剩余的 串为:
计分规则如下:消除了几个 就计几分。
直到消成空串时游戏结束。

对于一串全新的 串,由牛妹先手进行消除,两个人都以最优策略且以得分高为目标进行消除,请问最后,哪个人的得分会比较高?

  • 输入描述:

本题为多组测试数据,第一行输入一个正整数 ,代表测试数据组数。
对于每组测试数据,一行输入一个长度不超过 的 串,代表初始形态。

  • 输出描述

对于每组测试数据,如果牛妹得分高,则在第一行输出 ,第二行输出一个分数代表牛妹比牛牛高几分;如果牛牛得分高,则在第一行输出 ,第二行输出一个分数代表牛牛比牛妹高几分;如果两个人分数相同,则只需要在一行输出 .

  • 输入例子

2
111111
111011

  • 输出例子

Niumei
6
Niumei
1

  • 分析
  1. 先遍历字符串找到第一个相邻相同的子串,作为牛妹的子串,并根据子串是0还是1返回一个权重;
  2. 在原串中将该子串删除,再循环找下一个相同的子串,作为牛牛的子串,并返回权重;
  3. 如果没有相邻相同的子串,则将串中第一个字符返回,直到为空串;
  4. 牛妹得分为权重*子串长度之和,牛牛的也是;
  5. 输入接口用一个vector来装字符串,并遍历vector找子串;
  • 具体实现
    (1) 找寻子串函数
string xiaosingle(string s,int &rate){
    stringstream x_str;
    const char* pt = s.c_str();
    char tmp = *pt;
    if(s.size() == 1){
        if(s.c_str()[0] == '0')
            rate=0;
        else
            rate = 1;
        x_str << s.c_str()[0];
        return x_str.str();
    }
    for(size_t i=1;i<s.size();i++)
    {
        if(pt[i] == pt[i-1])
        {
            if(pt[i] == '0')
                rate = 0;
            else
                rate = 1;
            if(x_str.str().empty())
            {
               x_str << pt[i-1] << pt[i]; 
            }
            else
                x_str << pt[i];
        }
        else{

                if(x_str.str().empty())
                    continue;
                else{
                    break;
                }      
        }
    }
    if(x_str.str().empty()){
        if(s.c_str()[0] == '0')
            rate=0;
        else
            rate = 1;
        x_str << s.c_str()[0];
    }

    return x_str.str();
}

(2) 输入接口及得分

void xiaoxiaokan(const string s)
{
    string ss = s,s1,s2;
    int n_niumei=0,n_niuniu=0;
    int rate=0;
    int n1=0,n2=0;
    while(ss.size() != 0){
        s1.clear();s2.clear();
        s1 = xiaosingle(ss,rate);
            n1 = ss.find(s1);
            ss.erase(n1,s1.size());
            n_niumei += s1.size()*rate;
        if(ss.empty()){
            break;
        }
        else{
            s2 = xiaosingle(ss,rate);
                n2 = ss.find(s2);
                ss.erase(n2,s2.size());
                n_niuniu += s2.size()*rate;
        } 
    }
    if(n_niumei > n_niuniu){
        cout << "Niumei" << "\n" << n_niumei-n_niuniu << endl;
    }
    else if(n_niumei == n_niuniu){
        cout << "Draw" << endl;
    }
    else{
        cout << "Niuniu" << "\n" << n_niuniu-n_niumei << endl;
    }
}


void xiaoxiaole(const std::vector<string> str)
{
    for(auto s : str){
        xiaoxiaokan(s);
    }
}


int main(int argc,char** argv)
{
    int n;
    std::vector<string> s_v;
    cin >> n;
    for(int i=0;i<n;i++){
        string str;
        cin >> str;
        s_v.push_back(str);
    }
    xiaoxiaole(s_v);
    return 0;
}

(3) 测试结果
在这里插入图片描述

(4) 问题
本解法耗时77ms,占用内存较大,后期会试着进行优化,但奇怪的是本机上能够通过的例子,而且想了很多边界案例,比如输入1,0,10,01,00,11,101,010之类的,都能通过,但在牛客网上却通过不了,希望有知道的大佬可以指点迷津,万分感谢!

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值