2020牛客寒假算法基础集训营1 I nico和niconiconi

选nico都对惹

题目描述

nico平时最喜欢说的口头禅是niconiconi~。有一天nico在逛著名弹幕网站"niconico"的时候惊异的发现,n站上居然有很多她的鬼畜视频。其中有一个名为《让nico为你脑的视频吸引了她的注意。她点进去一看,就被洗脑了

"niconicoh0niconico*^vvniconicoG(vniconiconiconiconiconicoG(vniconico......"弹幕中刚开始有很多“nico*1 nico*2”等计数菌,但到后面基本上都是“计数菌阵亡”的弹幕了。nico也想当一回计数菌。她认为:"nico" 计 a 分,"niconi" 计 b 分,"niconiconi" 计 c 分。她拿到了一个长度为 n 的字符串,请帮她算出最大计数分数。
注:已被计数过的字符不能重复计数!如"niconico"要么当作"nico"+"nico"计 a * 2 分,要么当作"niconi"+"co"计 b 分。

输入

19 1 2 5
niconiconiconiconi~

输出

7

思路:

我楞了半天没发现是个线性DP问题,tcl

dp[i]表示前i - 1个最大的分数,那么转移方程很明显,首先dp[i + 1] = dp[i],如果当前没有新的nico···出现就是前面的分数了,如果当前字母是o,并且前面有nic,说明当前位置出现了一个新的nico,那么dp[i + 1] = max(dp[i + 1],dp[i - 3] + a),就是把当前分数和前面的三个字母和当前的o拼成nico后加上前面的位置的分数

如果当前字母是i,并且前面是n,说明出现了一个ni,前面如果还出现了nico,说明出现了niconi,那么dp[i + 1] = max(dp[i + 1],dp[i - 5] + b);为什么不和nico + a分比较呢?这个肯定出现再niconi之前,那么上面的过程一定计算过了,每次都会把前面的分数直接给当前位置,所以不用比较了。

如果是i,前面是niconicon,说明构成了niconiconi,和上面一样,dp[i + 1] = max(dp[i + 1],dp[i - 8] + c,dp[i - 8] + a + b,dp[i - 8] + a + a)

最后输出dp[len]就好了

#include <bits/stdc++.h>
using namespace std;
const int N = 301000;
char s[N];
typedef long long ll;
ll dp[N];
ll n, a, b, c;
int main()
{
	ios::sync_with_stdio(0);
	cin >> n >> a >> b >> c;
	cin >> s;
	memset(dp, 0, sizeof dp);
	int len = strlen(s);
	for (int i = 0; i < len; i++){
		dp[i + 1] = dp[i];
		if(s[i] == 'o' && i - 3 >= 0){
			if(s[i - 1] == 'c' && s[i - 2] == 'i' && s[i - 3] == 'n'){
				dp[i + 1] = max(dp[i], dp[i - 2] + a);
			}
		}
		else if(s[i] == 'i'){
			if(i - 5 >= 0){
				if(s[i - 1] == 'n' && s[i - 2] == 'o' && s[i - 3] == 'c' && s[i - 4] == 'i' && s[i - 5] == 'n'){
					dp[i + 1] = max(dp[i + 1], dp[i - 4] + b);
				}
			}
			if(i - 9 >= 0){
				if(s[i - 1] == 'n' && s[i - 2] == 'o' && s[i - 3] == 'c' && s[i - 4] == 'i' && s[i - 5] == 'n'
				&& s[i - 6] == 'o' && s[i - 7] == 'c' && s[i - 8] == 'i' && s[i - 9] == 'n'){
					dp[i + 1] = max(dp[i + 1], dp[i - 8] + c);
					dp[i + 1] = max(dp[i + 1], dp[i - 8] + b + a);
					dp[i + 1] = max(dp[i + 1], dp[i - 8] + a + a);
				}
			}
		}
	}
	cout << dp[len] << "\n";
	return 0;
}
发布了165 篇原创文章 · 获赞 11 · 访问量 9633

猜你喜欢

转载自blog.csdn.net/weixin_43701790/article/details/104171768
今日推荐