https://codeforces.com/contest/1550/problem/B
有一点啰嗦的题解
INPUT
3
3 2 0
000
5 -2 5
11001
6 1 -4
100111
OUTPUT
6
15
-2
题意
给T,给T组数据输入,每组数据中带有一个n、a、b,以及一个长度为n的只有 ‘ 0和1 ’ 构成的串,我们可以选定 连续相同子串(尤为注意长度可以为1)消除并获得 : l删去 * a + b的分数,剩下的自动补齐。
例如:串为001100,你可以选定中间 ‘11’ 子串并删去,获得: a * 2(‘11’串的长度) + b的分数,然后原串变成 ‘ 0000 ’ 继而选中剩下的全部,分数再加上 : a * 4 + b 的分数
题目输出能获得的最高分数
解法
首先获得分数的公式的前面半部分是 l * a,所以根据加法结合律可以得出一部分得分是固定的,即 n字符串长度 * a,需要注意的地方是b的取值,消去子串了多少次就会加上多少个b的值,但b的值有正有负,下面分情况讨论
- b是正数
所以我们得保证消去操作次数最多,那就从头消到位。
假如串为 ‘01001’
-> ‘1001’
-> ‘001’
-> ‘01’
-> ‘1’
->完
这样便获得最大操作次数
答案为 n * b + n * a - b是负数
那我们统计出 关于 ‘ 0 ’ 连通块的个数和 ’ 1 ’ 连通块的个数(连通块:一片区域 或长度 都是一个数)(难点所在
如‘0110001110000110’,
-> ‘ 0 ’的连通块个数为4
-> ‘ 1 ’的连通块个数为3
然后我们对最小个数的进行消去操作,所以例子中只有3个连通块的 ‘ 1 ’ 被三次操作消除,最后剩余一个全是 ‘ 0 ’的串,再进行一次操作结束。
操作演示
->0110001110000110
->00001110000110
->00000000110
->000000000
->完
答案为 n * a + b * ( min ( num0 , num1 ) + 1)
AC代码 ( 具有操作难度在统计连通块 , 12行开始)
#include<bits/stdc++.h>
using namespace std;
char e[105];
int main()
{
int T; cin>>T;
while(T--)
{
int len,a,b;
cin>>len>>a>>b>>e;
int num0 = 0,num1 = 0;
bool flag0 = false;
bool flag1 = false;
for(int i = 0;i<len;i++)
{
if(e[i] == '0')
{
if(flag0 == false)
{
flag0 = true;
flag1 = false;
num0++;
}
}
if(e[i] == '1')
{
if(flag1 == false)
{
flag1 = true;
flag0 = false;
num1++;
}
}
}
if(b > 0)
cout<<len * a + len * b<<endl;
else
cout<<b * (min(num0,num1) + 1) + len * a<<endl;
}
return 0;
}
如有更好的方法或意见可以说一下哈ε=ε=ε=┏(゜ロ゜;)┛