鄙人不才,此中鄙陋甚多,望海涵!!!
题目大意:n+1个点,相邻2点间有一条有向边,共n条边,从某个点以某个方向走一步,其他边就会都反向,相当于走偶数次正常,走奇数次就翻转,问从每个点出发最多可以到达多少个点!
图示:
图中的圈圈是路,星星是点,画图是为了更好的观察dp过程!
题目分析:我们可以把每个点分2个方向,即向左走和向右走,我们来分析左走的过程!
既然想要实现状态转移,那必然需要计算出当前状态需要从哪个状态转移来的那个状态,所以我们从左往右遍历!
对于第一个点 be[0]=0
,(be表示向左可达的点数),be[1]就要看第一条路的方向了,若为左,则为1,接下来就是分析第二个到第n个点了,每次分析一个点i,它左边的路为s[i-1],若s[i-1]==’L’ 同时 s[i-2]==’R’ 那我们便能实现状态转移,be[i]=be[i-2]+2
,否则就简单了,具体见代码,向右走也是一样的!
C++代码
#include<iostream>
using namespace std;
const int N=3e5+10;
char s[N];
int be[N],bf[N];
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
scanf("%s",s);
//从左走
be[0]=0;
be[1]= (s[0]=='L') ? 1 : 0;
for(int i=2;i<=n;i++)
{
if(s[i-1]=='L')
{
if(s[i-2]=='R') be[i]=be[i-2]+2;
else be[i]=1;
}
else be[i]=0;
}
//从右走
bf[n]=0;
bf[n-1]= (s[n-1]=='R') ? 1 : 0;
for(int i=n-2;i>=0;i--)
{
if(s[i]=='R')
{
if(s[i+1]=='L') bf[i]=bf[i+2]+2;
else bf[i]=1;
}
else bf[i]=0;
}
for(int i=0;i<=n;i++) printf("%d ",be[i]+bf[i]+1);
puts("");
}
return 0;
}