这题我发现大部分神犇都是用DP做的,然而需要吗?


首先我们可以考虑暴力,我们可以外层枚举哪一局换手势,内层算能赢多少局,这样复杂度是的。

之后我没就可以考虑优化,我们发现外层循环是优化不掉的,至少很难优化掉,我们可以优化内层使得查询每一次是的,怎么办呢?很显然我们只要用一个前缀和维护。计算赢多少局时我们只需要看输给他的那个手势出了多少次就行了。

细节声明:

1,要开三个前缀和数组来维护赢多少局(一共三种手势

2,当我们计算换了之后的手势等赢多少局时,应该是是当前下标。

3,别忘了还要分别枚举换之前手势是什么,和换之后是什么。由于可能不换,所以只要写一下如下循环就可以了

for(int i=1;i<=3;i++)
{
    for(int j=1;j<=3;j++)//我们不需要判断i是否等于j,因为可以一直不换
    {
    }
}

这样我们的代码就出来啦!

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin>>n;
    int a[n+5];
    int h[n+5],s[n+5],p[n+5];//三个前缀和数组
   //A数组其实没啥用
    s[0]=h[0]=p[0]=0;
    for(int i=1;i<=n;i++)
    {
        char c;
        cin>>c;
        s[i]=s[i-1];
        h[i]=h[i-1];
        p[i]=p[i-1];
        if(c=='H')
        {
            a[i]=1;
            h[i]++;//记录蹄子出了多少次
        }
        if(c=='S')
        {
            a[i]=2;
            s[i]++;//记录剪刀出了多少次
        }
        if(c=='P')
        {
            a[i]=3;
            p[i]++;//记录纸出了多少次
        }
    }if(max(p[n],max(h[n],s[n]))==n)//如果全是一个手势就输出N
    {
        cout<<n;
        return 0;
    }
    int ans=0;
    for(int i=1;i<=3;i++)
    {
        for(int j=1;j<=3;j++)
        {
            for(int k=1;k<=n;k++)
            {
                int sum=0;
                if(i==1)
                sum+=s[k];
                if(i==2)
                sum+=p[k];
                if(i==3)
                sum+=h[k];
                if(j==1)
                sum+=s[n]-s[k-1];
                if(j==2)
                sum+=p[n]-p[k-1];
                if(j==3)
                sum+=h[n]-h[k-1];
                       //算赢了多少局
                ans=max(ans,sum);//记录最大值
            }
        }
    }
    cout<<ans;//输出
    return 0;
}