题目链接:http://ace.delos.com/usacoprob2?a=RfmQrEONAFb&S=beads今天开始重做usaco了。上次是去年这个时候了,一眨眼一年就过去了。做了两个月才到4.3,后来就没做了。
现在重新开始吧。
beads这题,比较巧妙的地方就是把字符串复制一份,从而就避免了边界检查。
用left[0][i]来记录从某一点向左可以收集到的最长r色beads数
用left[1][i]来记录从某一点向左可以收集到的最长b色beads数
right数组类推。
显然,如果i为r色,则向左可以收集到的最长r色为left[0][i-1]+1.可以向左收集到的最长b色为0。
如果i为b色,类推。
如果i为w色,i即可做r,也可做b.所以各自加1.
代码如下:
#include <iostream>
#include <fstream>
using namespace std;
ifstream fin("beads.in");
ofstream fout("beads.out");
#ifdef _DEBUG
#define out cout
#define in cin
#else
#define out fout
#define in fin
#endif
//为简化代码,在数组前后各加1位,这样i+1,i-1不会越界,也无需对边界情况特殊处理。
int l[2][702];
int r[2][702];
void solve()
{
int num;
in>>num;
string s;
in>>s;
s+=s;
memset(r,0,sizeof(l));
memset(r,0,sizeof(r));
for(int i=s.size();i>=1;--i){
if(s[i-1]=='r'){
r[0][i] = r[0][i+1]+1;
r[1][i] = 0;
}else if(s[i-1]=='b'){
r[0][i] = 0;
r[1][i] = r[1][i+1]+1;
}else{
r[0][i] = r[0][i+1]+1;
r[1][i] = r[1][i+1]+1;
}
}
for(int i=1;i<=s.size();++i){
if(s[i-1]=='r'){
l[0][i] = l[0][i-1]+1;
l[1][i] = 0;
}else if(s[i-1]=='b'){
l[0][i] = 0;
l[1][i] = l[1][i-1]+1;
}else{
l[0][i] = l[0][i-1]+1;
l[1][i] = l[1][i-1]+1;
}
}
int res = INT_MIN;
for(int i=1;i<=num;++i){
res = max(res, max(r[0][i],r[1][i])+max(l[0][i+num-1],l[1][i+num-1]));
}
// 在出现重叠的情况下,res会大于num.最大只能是num
res = min(res,num);
out<<res<<endl;
}
int main(int argc,char *argv[])
{
solve();
return 0;
}