D - The World Is Just a Programming Task (Easy Version)思维

题意:
有一个括号序列,你可以选择两个位置i,j(i可以等于j),进行交换。使得最后的循环位置(i的数目)最大。

循环位置:i(0<=i<len),将前i个字符移到最后,得到的新序列是合法的括号序列。

)()()( 的循环位置有 1、3、5
)((()))( 的循环位置有 1、7
思路:
由于n很小,我们可以先暴力枚举交换的位置i,j,然后o(n)记录答案,如何on记录答案呢,我们定义前缀值,为遇到左括号+1,遇到右括号-1,当然如果最终的前缀值不为0,显然这种情况肯定不是最佳的,这题其实是有一个结论的,答案就是前缀的最小值的个数,下面我们来证明一下,反证法:如果不是前缀的最小值,那么也就是比它大,假设这个前缀的最小值不在这个范围内,那么就是该前缀不满足括号序列的左括号数大于等于右括号数;反之,如果在当前枚举的范围内,也就是包括在其中,那么不包括前缀的后半部分左括号肯定大于右括号,放入后缀中就没有人和他匹配了,也不成立。

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<set>
#include<vector>
using namespace std;
const int N=510;
typedef long long ll;
int sum[N][2];
int main()
{
    int n;
    string s;
    cin>>n>>s;
    s=' '+s;
    int maxv=0;
    int o1=1;
    int o2=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=i;j<=n;j++)
        {
            string ss=s;
            swap(ss[i],ss[j]);
            memset(sum,0,sizeof sum);
            int lc=0;
            int rc=0;
            bool flag=1;
            int  tt=0;
            bool ff=1;
            int minv=0;
            for(int k=1;k<=n;k++)
            {
                if(ss[k]=='(')   lc++;
                else    lc--;
                minv=min(minv,lc);
            }

            if(lc)
                flag=0;
            /*
            if(i==1 && j==10)
            {
                cout<<ss<<endl;
                for(int k=1;k<=n;k++)
                    cout<<sum[k][0]<<" "<<sum[k][1]<<endl;
            }
            */
            if(flag)
            {
                int lc=0;
                int ct=0;
                for(int k=1;k<=n;k++)
                {
                    if(ss[k]=='(')   lc++;
                    else    lc--;
                    if(lc==minv)
                        ct++;
                }
                if(ct>maxv)
                {
                    maxv=ct;
                    o1 = i;
                    o2 = j;
                }
            }
        }
    }
        cout<<maxv<<endl;
        cout<<o1<<" "<<o2<<endl;
     return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值