1745. Yet Another Answer

http://acm.timus.ru/problem.aspx?space=1&num=1745

题目大意:

可以是任意的顺序,在满足括号匹配的情况下,求组合成的字符串长度最长

思路:

先将每一个字符串进行处理,处理时将匹配的去掉 比如说  { )(()(())(} 处理后就变成了 {)(  (}

当然字符串的长度是没有变化的 处理后的字符串假如说 左括号的个数为L 右括号的个数为R

我们必须确定一个正确的顺序,可以让我们从头到尾的逐个决定是否选用当前字符串,而且不影响最优结果

字符串有 L>R,L<R 和 L=R 三种情况,对于L>R的字符串要放在前面 因为每一个这样的字符串都可以使

左括号 — 右括号 的值变大,

而对于 L<R 的情况对应放在最后,L=R的情况放在中间

对于L<R的字符串之间 需要把 R 小的放在前面, 对于L>R的情况 要用对称思想去确定顺序

确定顺序之后,剩下的就DP就可以了

代码:

#include<iostream>

#include<stack>

#include<cstdio>

#include<queue>

#include<cstring>

#include<algorithm>

#include<vector>

#include<set>

#include<map>

#include<string>

#include<cmath>



using namespace std;



typedef long long ll;

typedef pair<int,int> pp;

const double eps=1e-9;

const int INF=0x3f3f3f3f;

const int N=1002;

const int M=10002;

struct node

{

    string s;

    int lk,rk;

    int index;

}x[N];

int dp[N][M];

int func(const node& a)

{

    if(a.lk-a.rk>0) return 1;

    if(a.lk-a.rk<0) return -1;

    return 0;

}

bool cmp(const node& a,const node& b)

{

    int lf=func(a),rf=func(b);

    if(lf==1&&rf==1)

    return a.rk<b.rk;

    if(lf==-1&&rf==-1)

    return a.lk>b.lk;

    return lf>rf;

}

int main()

{

    //freopen("data.in","r",stdin);

    int n;

    while(cin>>n)

    {

        for(int i=0;i<n;++i)

        {

            cin>>x[i].s;

            x[i].index=i+1;

            stack<char>st;

            for(unsigned int j=0;j<x[i].s.size();++j)

            {

                if(st.empty()||x[i].s[j]=='('||st.top()==')')

                {

                    st.push(x[i].s[j]);

                }else

                {

                    st.pop();

                }

            }

            x[i].lk=x[i].rk=0;

            while(!st.empty())

            {

                if(st.top()=='(') ++x[i].lk;

                else ++x[i].rk;

                st.pop();

            }

        }

        sort(x,x+n,cmp);



        memset(dp,-1,sizeof(dp));

        dp[0][0]=0;

        for(int i=0;i<n;++i)

        {

            for(int j=0;j<M;++j)

            if(dp[i][j]!=-1)

            {

                dp[i+1][j]=max(dp[i+1][j],dp[i][j]);

                if(j>=x[i].rk)

                dp[i+1][j-x[i].rk+x[i].lk]=max(dp[i+1][j-x[i].rk+x[i].lk],(int)(dp[i][j]+x[i].s.size()));

            }

        }

        vector<int>vt;

        int i=n,j=0;

        while(i>0)

        {

            if(dp[i-1][j]==dp[i][j])

            i=i-1;

            else

            {

                vt.insert(vt.begin(),i-1);

                j=j-x[i-1].lk+x[i-1].rk;i=i-1;

            }

        }

        cout<<dp[n][0]<<" "<<vt.size()<<endl;

        for(unsigned int i=0;i<vt.size();++i)

        {

            if(i>0) cout<<" ";

            cout<<x[vt[i]].index;

        }

        cout<<endl;



    }

    return 0;

}

 

 

你可能感兴趣的:(r)