題目鏈接: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;
}