青训营-多米诺骨牌均衡状态

30 阅读3分钟

问题描述

多米诺骨牌游戏规则非常简单,将骨牌按一定间距的尺寸排成单行,或分行排成一片。推倒第一张骨牌,其余发生连锁反应依次倒下,或形成一条长龙,或形成一幅图案。

小 A 觉得多米诺骨牌超级没意思,所以他想了点小花招。

小 A 将 n 个多米诺骨牌放在一条线上,每一块都垂直竖立。他同时将一些骨牌向左或向右推倒。注意:不会出现连续向左或者向右推的情况。 每过一秒,被推向左边或右边的骨牌会将左边或右边的相邻骨牌推倒。当一个骨牌,其左边倒向它的骨牌数目与其右边倒向它的骨牌数目相等时,由于力的平衡,该骨牌将依然保持竖立。

给定小 A 最初推骨牌的方向,求出最后依然保持竖立的骨牌数目和位置。

输入格式

输入数据第一行包括一个整数 n(1≤n≤3000),表示这一行多米诺骨牌的数目。下一行包括一个长度为 n 的字符串,字符串的第 i 个字符意义如下:

“L”,第 i 个字符将要被向左推。

“R”,第 i 个字符将要被向右推。

“.”,第 i 个字符不会被推。

输出格式

首先输出保持竖立的骨牌数目。如果保持竖立的骨牌数目不为 0,下一行输出保持竖立的骨牌的位置,骨牌位置从 1 到 n。

每两个数之间用一个空格隔开,注意最后一个数后面没有空格。

输入样例

14

.L.R...LR..L..

5

R....

1

.

输出样例

4

3 6 13 14

0

1

1

解题思路

为了解决这个问题,我们首先要了解骨牌在什么情况下会树立

  • 骨牌左侧向左倒右侧向右倒,则骨牌树立(题目条件:不会出现连续向左或者向右推的情况)
  • 骨牌左侧向右倒,右侧向左倒,且左右之间骨牌数为奇数,中间骨牌树立 找到骨牌,判断左右两端的状态,若满足上述条件,则树立

具体步骤

1.寻找骨牌区间
采用双指针来找寻'.'(骨牌区间)
i代表骨牌开始的下标,j表示骨牌结束的下一个牌
2.判断是否树立
利用left记录data[i-1]
利用right记录data[j]
注意: 如果骨牌在边界,我们需要将不在范围内的data[i]与data[j]赋值为'.' 以便之后进行判断。

char left=(i-1>=0)?data[i-1]:'.';
        char right=(j<num)?data[j]:'.';

通过比较leftright'L','R',即可判断骨牌是否树立。(等于不好判断,我们可以利用不等于进行简化)

补充:

std::to_string(data) 十进制数字转为字符串

算法实现

#include <iostream>
#include <string>
#include<string.h>
#include<vector>

std::string solution(int num, std::string data) {
    // Please write your code here

  std::vector<int> result;
  int i=0;
  while(i<num){
    if(data[i]=='.'){
        int j=i;
        while(data[j]=='.'&&j<num)j++;//查找骨牌区间
        char left=(i-1>=0)?data[i-1]:'.';//查看骨牌区间左部
        char right=(j<num)?data[j]:'.';//查看骨牌区间右部
        if(left=='R'&&right=='L'&&(j-i)%2==1){
          result.push_back(i+(j-i)/2+1);//骨牌左侧向右倒,右侧向左倒,且左右之间骨牌数为奇数,中间骨牌树立
        }else if(left!='R'&&right!='L'){//骨牌左侧向左倒或右侧向右倒,则骨牌树立
            for(int k=i;k<j;k++) result.push_back(k+1);
        }  
        i=j;      
    } else i++;
  }

std::string count;//输出
count=count+std::to_string(result.size())+':';
for(int i=0;i<result.size();i++)
{
    count+=std::to_string(result[i])+',';
}
count=count.substr(0,count.length()-1);

return count;

  
}

int main() {
    //  You can add more test cases here
    std::cout << (solution(14, ".L.R...LR..L..") == "4:3,6,13,14") << std::endl;
    std::cout << (solution(5, "R....") == "0") << std::endl;
    std::cout << (solution(1, ".") == "1:1") << std::endl;

    return 0;
}