网上题解几乎是C++,但是C语言也可以写。
题目分析
-
题目给出一个包含FEB三种字符的字符串,其中F可以是E,也可以是B
-
要求计算F取不同值的所有情况下,字符串可能的“价值”
-
字符串中B和E是写定的,BB和EE对价值的贡献固定为1
-
再纳入F在不同语境下的影响,发现在“BFE”中,价值最少是1,最多也是1;在“BBFBE”中,价值最少是1,最多是3
-
可以发现价值的最大最小值可以随着F串的不同情况上下浮动
-
再发现在“FFFFFF”、“XXXFFF”、“FFFXXX”中(X != F)【即首尾是F】,可能价值是公差为1的等差数列;首尾不是F的情况下,可能价值是公差为2的等差数列
-
再发现F串中F数量的奇偶和两边的字符是否一致对价值的可能最大最小值有所影响
-
归纳总结规律,依照逻辑写出代码
规律
假设一个F串中F个数为n
形式 | 该串贡献价值最大值 | 该串贡献价值最小值 | 公差 |
---|---|---|---|
输入全F | n - 1 | 0 | 1 |
首尾的F串 | n | 0 | 1 |
两边不同 奇数个F | n | 1 | 2 |
两边不同 偶数个F | n | 0 | 2 |
两边相同 偶数个F | n + 1 | 0 | 2 |
两边相同 奇数个F | n + 1 | 1 | 2 |
代码
因为可以求出价值的最大最小值以及公差,就可以直接输出结果了
#include<stdio.h>
#include<stdlib.h>
int main()
{
int flag = 0;// flag == 1 是公差为1的等差数列;flag == 0 是公差为2的等差数列
int fl = 0;// 是否全是F 1是不全为F
int j = 0;
int n = 0;
scanf("%d", &n);
char ch[n+1];
scanf("%s", ch);
int max = 0, min = 0; // 价值的最大最小值
int i = 0;
for(i = 0; i < n; i++)
{
if(ch[i] == 'B' && i < n - 1)
{
fl = 1;
if(ch[i+1] == 'B')
{
max++;
min++;
}
}
if(ch[i] == 'E' && i < n - 1)
{
fl = 1;
if(ch[i+1] == 'E')
{
max++;
min++;
}
}
if(ch[i] == 'F')
{
max++;
}
}
if(fl == 0)
{
if(ch[n-1] != 'F')
{
fl = 1;
}
}
if(fl)
{
i = 1;
while(i < n - 1)
{
int len = 0;
if(ch[i] != 'F')
{
i++;
}
else if(ch[i] == 'F')
{
j = i;
while(ch[j] == 'F' && j < n - 1) //搜索到一个F串
{
j++;
len++;
}
if(ch[i - 1] != ch[j] && len % 2)// 两边不同 奇数个F
{
min++;
if((i == 1 && ch[0] == 'F')|| (j == n - 1 && ch[n - 1] == 'F'))// 如果该F串在首尾
{
min--;
}
}
if(ch[i - 1] == ch[j] && len % 2 == 0)//两边相同 偶数个F
{
min++;
max++;
if((i == 1 && ch[0] == 'F')|| (j == n - 1 && ch[n - 1] == 'F'))// 如果该F串在首尾
{
min--;
max--;
}
}
if(ch[i - 1] == ch[j] && len % 2)//两边相同 奇数个F
{
max++;
if((i == 1 && ch[0] == 'F')|| (j == n - 1 && ch[n - 1] == 'F'))// 如果该F串在首尾
{
max--;
}
}
i = j;
}
}
}
if(fl == 0)
{
flag = 1;
max--;
}
if(ch[0] == 'F')
{
flag = 1;
}
if(ch[n - 1] == 'F')
{
flag = 1;
}
if(flag)
{
printf("%d\n", (max - min) + 1);
for(i = min; i <= max; i++)
{
printf("%d\n", i);
}
}
else
{
printf("%d\n", (max - min)/2 + 1);
for(i = min; i <= max; i+=2)
{
printf("%d\n", i);
}
}
return 0;
}