第15届浙江省程序竞赛 部分题解

D Sequence Swapping

题意:输入一串只含 '(' , ')' 的字符串,第 i 个字符对应vi 的分数,如果第i个字符是 '(' ,第i+1个字符是 ')' ,那么这两个字符可以互换,同时vi 和vi+1 也要互换,并且得到vi * vi+1的分数,求该字符串的最大分数。

思路:很明显 '(' 能换多少次取决于 '(' 后面有几个 ')' ,设d[ i ][ j ]为倒数第i个 '(' 换到 j  位置时取得的最大分数,那么             d[ i ][ j ]=min(d[ i ][ j ], vi*vi+1 + vi*vi+2 +....+vi*vj+max(d[ i-1 ][ j+1 ], d[ i-1 ][ j+2 ],,,,d[ i-1 ][ n ] )  )

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
char s[1005];
long long a[1005];
int t[1005];
long long d[1005][1005];
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n,i,j,k;
		long long ans=0;
		vector<int>v;
		scanf("%d",&n);
		scanf("%s",s+1);
		for(i=1;i<=n;i++)
		scanf("%lld",&a[i]);
		v.push_back(0);
		for(i=n;i>=1;i--)
		{
			if(s[i]=='(')
			v.push_back(i);
		}
		memset(d,0,sizeof(d));
		for(i=1;i<v.size();i++)
		{	
			k=v[i];  //第i个'('的下标 
			int sum=0;
			int tot=0;
			for(j=k+1;j<=n;j++)
			if(s[j]==')')
			t[++tot]=j;  //把i后面所有的')'下标存起来 
			d[i][k]=d[i-1][k+1];  //赋予初始值 
			for(j=k+1;j<=k+tot;j++)
			{
				d[i][j]=sum+a[k]*a[t[j-k]]+d[i-1][j+1]; //这个d[i][j]表示倒数第i个'('移到i之后第j个')'时的最大得分 
				sum+=a[k]*a[t[j-k]];                  //而d[i-1][j]表示倒数第i-1个'('移动到i之后多于或等于第j个')'时的最大得分 
				ans=max(ans,d[i][j]);
			}
			int p;
			for(p=k;p>=2;p--)  //找到i前面一个(的的下标 
			if(s[p-1]=='(')
			break;
			for(j=k+tot-1;j>=p;j--)
			d[i][j]=max(d[i][j],d[i][j+1]);//把d[i][j]更新为倒数第i个'('移到i后面大于或等于第j个')'时的最大得分 
		}
		printf("%lld\n",ans);
	}
}

猜你喜欢

转载自blog.csdn.net/ccsu_cat/article/details/80294613