题意
一个环形项链,有rbw三种珠子,r代表red,b代表blue,w代表white,从任意一个位置断开,两端分别取珠子,同一端取的珠子要相同颜色,w可以染成想要的颜色,即既可当作r也可以当作b,求最多取得的珠子个数。最多有350个珠子。
分析
可以枚举断开的位置,然后模拟取珠子。也可以枚举起点位置。还可以dp做。
代码
枚举断点
代码语言:javascript复制#include<cstdio>
#include<algorithm>
#define N 355
using namespace std;
char a;
int b[N];
int n,ans;
int solve(int p,int dir) //p为起始点,dir为方向,求最多取几颗
{
int len=0;//取了的珠子个数,最多取n颗珠子
for(int j=p n; len<n; len ,j =dir) //j为当前位置 n,当前位置为j%n
{
if(b[p] && b[j%n] && b[j%n]!=b[p])
break;
if(!b[p])//每次取珠子都要符合p位置的颜色,若p位置是w,就要更新p
p=j%n;
}
return len;
}
int main()
{
scanf("%d ",&n);
for(int i=0; i<n; i )
{
a=getchar();
b[i]=a=='b'?1:a=='r'?2:0;// b--1 r--2 w--0
}
for(int i=0; i<n; i )//枚举断点
ans=max(ans,solve(i,-1) solve(i 1,1));
ans=min(ans,n);//可能同一颗被两次计算过,但只出现在全都取的情况里
printf("%dn",ans);
return 0;
}
枚举起点
代码语言:javascript复制#include<cstdio>
#include<algorithm>
#include<iostream>
#include<string>
using namespace std;
int n,ans;
string s;
int main()
{
cin>>n>>s;
s =s;
for(int i=0,j; i<n; i ) //以i为第一段的起点,不是切开的位置
{
char now=s[i];
int len=0;
int times=now=='w'?3:2;//如果当前是白色,那么需要找三段相同颜色的否则找两段
j=i;
while(times--)
{
while(j<i n&&(s[j]==now||s[j]=='w'))
{
len ;
j ;
}
now=s[j];
}
ans=max(ans,len);
}
cout<<ans<<endl;
return 0;
}
DP
代码语言:javascript复制#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#define N 720
using namespace std;
int n,ans;
string s;
int l[N][2],r[N][2];
int main(){
cin>>n>>s;
s =s;
for(int i=1;i<2*n;i ){
l[i][0]=l[i-1][0] 1;
l[i][1]=l[i-1][1] 1;
if(s[i-1]=='r')
l[i][1]=0;
else if(s[i-1]=='b')
l[i][0]=0;
}
for(int i=2*n-1;i>=0;i--){
r[i][0]=r[i 1][0] 1;
r[i][1]=r[i 1][1] 1;
if(s[i]=='r')
r[i][1]=0;
else if(s[i]=='b')
r[i][0]=0;
}
for(int i=0;i<2*n;i )
ans=max(ans,max(l[i][0],l[i][1]) max(r[i][0],r[i][1]));
ans=min(ans,n);
cout<<ans<<endl;
return 0;
}