zoj 4027 2018浙江acm省赛 Problem D. Sequence Swapping
程序员文章站
2022-05-21 12:10:31
...
链接: https://cn.vjudge.net/problem/ZOJ-4027
思路: dp 第二次做还是没有做出来。。。不过的确是个好题。
首先就是要确定dp状态的定义,这里我把dp[i][j] 定义为将第i个左括号移动到 位置>=j 的最大价值。
其实可以发现每个左括号其实都是有一个可移动上下界范围的。我如果想要将第i个括号移动到位置j 那么肯定第 i+1 个括号在 >=j+1 的位置。
那么 dp[i][j] = max( dp[i][j+1] , dp[i+1][j+1] + 移动到这里所需要的花费 )
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf = 1e18+5;
const int N = 1005;
ll dp[N][N];
ll cost[N][N];
ll sum2[N][N];
char s[N];
ll val[N];
int inde[N];
int n;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
scanf("%s",s+1);
for(int i=1;i<=n;i++)
{
scanf("%lld",&val[i]);
}
for(int i=0;i<=n+2;i++)
{
for(int j=0;j<=n+2;j++)
{
sum2[i][j]=cost[i][j]=0;
dp[i][j]=-inf;
}
}
for(int i=1;i<=n;i++)
{
int c1=0,c2=0;
for(int j=i;j<=n;j++)
{
if(s[j]==')') c2++;
else c1++;
sum2[i][j]=c2;
}
}
int cnt=0;
for(int i=1;i<=n;i++)
{
if(s[i]==')') continue;
++cnt;
int tmp=0;
ll C=0;
for(int j=i;j<=n;j++)
{
if(s[j]==')')
{
tmp++;
C+=val[j];
cost[cnt][tmp]=C;
}
}
}
cnt=0;
for(int i=1;i<=n;i++)
{
if(s[i]=='(')
{
inde[++cnt]=i;
}
}
ll ans=0;
int in,up,down;
in=inde[cnt]; up=sum2[in][n]+in; down=in;
for(int j=up;j>=down;j--)
{
int x=j-down;
dp[cnt][j]=max(dp[cnt][j+1],val[in]*cost[cnt][x]);
ans=max(ans,dp[cnt][j]);
}
for(int j=down-1;j>=1;j--)
{
dp[cnt][j]=max(dp[cnt][j],dp[cnt][j+1]);
}
for(int i=cnt-1;i>=1;i--)
{
in=inde[i]; up=sum2[in][n]+in; down=in;
for(int j=up;j>=down;j--)
{
int x=j-down;
dp[i][j]=max(dp[i+1][j+1]+val[in]*cost[i][x],dp[i][j+1]);
if(i==1) ans=max(ans,dp[i][j]);
}
for(int j=down-1;j>=1;j--)
{
dp[i][j]=max(dp[i][j],dp[i][j+1]);
}
}
printf("%lld\n",ans);
}
return 0;
}
/*
4
6
)())()
1 3 5 -1 3 2
6
)())()
1 3 5 -100 3 2
3
())
1 -1 -1
3
())
-1 -1 -1
*/