DP-牛客寒假集训营1- nico和niconiconi
题目:
题意:
给
定
一
个
字
符
串
给定一个字符串
给定一个字符串
对
于
子
串
“
n
i
c
o
”
可
得
a
分
对于子串“nico”可得a分
对于子串“nico”可得a分
对
于
子
串
“
n
i
c
o
n
i
”
可
得
b
分
对于子串“niconi”可得b分
对于子串“niconi”可得b分
对
于
子
串
“
n
i
c
o
n
i
c
o
n
i
”
可
得
c
分
对于子串“niconiconi”可得c分
对于子串“niconiconi”可得c分
现
输
入
字
符
串
长
度
n
,
分
数
a
,
b
,
c
,
字
符
串
s
现输入字符串长度n,分数a,b,c,字符串s
现输入字符串长度n,分数a,b,c,字符串s
问
s
的
最
大
得
分
是
多
少
问s的最大得分是多少
问s的最大得分是多少
题解:
计 d p [ i ] 代 表 前 i 个 字 符 的 计 数 最 大 值 。 那 么 可 得 转 移 方 程 : 计 dp[i]代表前 i个字符的计数最大值。那么可得转移方程: 计dp[i]代表前i个字符的计数最大值。那么可得转移方程:
①、
i
f
(
s
u
b
s
t
r
i
n
g
(
i
−
3
,
i
)
=
=
n
i
c
o
)
,
t
h
e
n
:
d
p
[
i
]
=
m
a
x
(
d
p
[
i
]
,
d
p
[
i
−
4
]
+
a
)
if(substring(i-3,i)==nico) ,then: dp[i]=max(dp[i],dp[i-4]+a)
if(substring(i−3,i)==nico),then:dp[i]=max(dp[i],dp[i−4]+a)
②、
i
f
(
s
u
b
s
t
r
i
n
g
(
i
−
5
,
i
)
=
=
n
i
c
o
n
i
)
,
t
h
e
n
:
d
p
[
i
]
=
m
a
x
(
d
p
[
i
]
,
d
p
[
i
−
6
]
+
b
)
if(substring(i-5,i)==niconi),then: dp[i]=max(dp[i],dp[i-6]+b)
if(substring(i−5,i)==niconi),then:dp[i]=max(dp[i],dp[i−6]+b)
③、
i
f
(
s
u
b
s
t
r
i
n
g
(
i
−
9
,
i
)
=
=
n
i
c
o
n
i
c
o
n
i
)
,
t
h
e
n
:
d
p
[
i
]
=
m
a
x
(
d
p
[
i
]
,
d
p
[
i
−
10
]
+
c
)
if(substring(i-9,i)==niconiconi),then:dp[i]=max(dp[i],dp[i-10]+c)
if(substring(i−9,i)==niconiconi),then:dp[i]=max(dp[i],dp[i−10]+c)
最 后 输 出 d p [ n ] 即 可 。 最后输出 dp[n] 即可。 最后输出dp[n]即可。
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e5+10;
int n;
ll a,b,c,dp[N];//dp[i]表示前i个字符的最大得分
string s;
int main()
{
cin>>n>>a>>b>>c;
cin>>s;
for(int i=0;i<s.size();i++)
{
if(i>=1) dp[i]=dp[i-1];//首先每增加一个字符,得分应当大于等于前一项,因此先赋值为前一项的值,防止递推“断开”
if(i>=3&&s.substr(i-3,4)=="nico")
dp[i]=max(dp[i],dp[i-3]+a);//不选择子串"nico"和选择子串"nico"在此前基础得a分两者之间取最大
if(i>=5&&s.substr(i-5,6)=="niconi")
dp[i]=max(dp[i],dp[i-5]+b);
if(i>=9&&s.substr(i-9,10)=="niconiconi")
dp[i]=max(dp[i],dp[i-9]+c);
}
cout<<dp[n-1]<<endl;
}