有n个石头在桌上摆成一排(in a row),有红的绿的蓝的。**算出至少拿走几块石头可以使得任意两个相邻的石头颜色都不同。**如果成排的两个石头之间没有其他石头则认为它们是相邻的。
输入
第一行输入一个[1,50]的整数n,表示桌上石头的(初始)数量。 下一行输入一个字符串s,表示桌上石头的颜色序列。我们将会把石头从左到右依次编号为1到n。用字符'R','G','B'分别表示红色、绿色、蓝色。
输出
输出一个整数,即问题的答案。
要分析出字符串中“两个(相邻同色)的”“三个的”“四个的”。。。即各个大小的色块各自的数量 每有一个“两个的”,次数+1 每有一个“三个的”,次数+2 每有一个“四个的”,次数+3 ... 每有一个“i个的”,次数+(i-1)
怎么分析? 对输入的字符串逐个字符检查,检查其右方有几个和它相同的字符,则可以确定该色块大小。每检查完一次,从这个色块右边的字符开始继续检查。
#include<iostream>
using namespace std;
int main()
{
int n;
cin >> n;
char* s = new char[n];//创建长度为n的字符数组s,表示石头颜色序列
cin >> s;
int* blocksize = new int[n + 1]();//创建长度为n+1的数组blocksize用于存放各个大小的色块的数量,下标即色块大小(因为色块最大的可能大小为n,需要有下标为n的项,所以数组容量要+1
int m;
int i = 0;
while (s[i] != '\0')
{
m = 1;
for (int j = i; s[j] == s[j + 1]; j++)m++;//该循环用于检查检查中色块的大小,循环完毕后,m表示该色块的大小(易错点:这里m的初始值应当为1)
blocksize[m]++;
i += m;
}//到这里各大小色块数量已统计完毕
int res = 0;
for (i = 0; i <= n; i++)
{
res += blocksize[i] * (i - 1);
}
cout << res;
return 0;
}
做这题时被一个常识性错误卡了相当长时间,就是用于检查色块大小的那个循环,原本用的是for,但在循环体中又有改变循环量的操作(i+=m),这类循环虽不是不能用,只是要很小心,比如做这题时的情况是,如果m的初值是0则没有问题,可是后来发现根据解题需要m的初值应当为1,改正其初值之后又不把for改为while,导致无法正确统计各大小色块数量。此外在我发现这个问题之前我总以为是数组的初始化问题,虽然最后问题不在这里但这特别是字符数组和动态数组的初始化基础还有待提升。此外还要注意不要重复创建变量(提示:for创建的变量仅在循环体内有用)。