1 条题解

  • 0
    @ 2025-5-7 11:48:20

    这道题很有意思,也比较有难度,是一个算式形式的动态规划,和区间dp还是有一定联系的,因为我们每次开始游戏时需要断开一条边,之后就变成了一条链,可以看做区间,这样,我们初步应该会想到f[l][r]来表示l到r合并后最大的价值。 !!但是,这样就会有一个非常谜的问题!最大值不仅是由最大值加和而来的,它还可能是由两个最小值乘来的(负负得正),这样题就没法做了,所以这个子问题不满足无后效性!只能另寻它法!虽然说这个子问题不合适,但是这离我们的正解也已经非常近了。 我们可以用f[l][r]表示l到r所能合成的最大值,然后f1[l][r]表示l到r能合成的最小值。为什么这就能满足无后效性呢,因为啊: 1.一个最大值无非就是由两个最大值相加,两个最大值相乘或者两个最小值相乘而得来的! 2.一个最小值无非就是由两个最小值相加,或两个最小值相乘,或前一个最小值和后一个最大值相乘,或后一个最小值和前一个最大值相乘而得来的! 所以,我们就能够依据上述关系写出状态转移方程,这里就不给出了; 这样呢,我们就能够用区间dp的套路安排循环!但是有一个巨大的问题,我们需要枚举首先断掉那条边!这样下来会很麻烦,怎么办呢。在处理动态规划的环形问题时,我们可以先把这个环断掉,从任意位置断掉,然后长度复制一条一模一样的链连接在其后,这样我们就可以通过区间的移动来达成首先断一条边的操作;因为区间每次向右移动一位,都代表着把原来断的那条边接上,在把现有的最左边这条边断掉!这样就能达成一个。枚举先断哪条边的作用!

    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    long long dp[101][101][2];
    inline long long read()
    {
    	long long f=1,ans=0;char c;
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    	return f*ans;
    }
    long long n;
    char strr;
    long long a[101];
    char st[101];
    long long inf=2<<30-1;
    void init()
    {
    	
    	for(long long i=1;i<=n;i++)
    		for(long long j=1;j<=n;j++) dp[i][j][1]=inf,dp[i][j][0]=-inf;
    }
    long long cx(long long a,long long b,char xx)
    {
    	if(xx=='*') return a*b;
    	return a+b;
    }long long sz[101];char str[101];
    long long dp_sry()
    {
    	for(long long k=1;k<n;k++)
    	{
    		for(long long i=1;i<=n&&i+k<=n;i++)
    		{
    			long long j=i+k;
    			for(long long t=i;t<j;t++)
    			{
    			
    				dp[i][j][0]=max(dp[i][j][0],max(max(cx(dp[i][t][0],dp[t+1][j][0],str[t]),cx(dp[i][t][0],dp[t+1][j][1],str[t])),max(cx(dp[i][t][1],dp[t+1][j][0],str[t]),cx(dp[i][t][1],dp[t+1][j][1],str[t]))));
    				dp[i][j][1]=min(dp[i][j][1],min(min(cx(dp[i][t][0],dp[t+1][j][0],str[t]),cx(dp[i][t][0],dp[t+1][j][1],str[t])),min(cx(dp[i][t][1],dp[t+1][j][0],str[t]),cx(dp[i][t][1],dp[t+1][j][1],str[t]))));
    			}
    			
    		}
    	}
    	return max(dp[1][n][0],dp[1][n][1]);
    }
    long long sry[101];
    int main()
    {
    	n=read();
    	for(long long i=1;i<=n;i++)
    	{
    		cin>>strr>>a[i];
    		a[i+n]=a[i];
    		if(strr=='t') st[i]=st[i+n]='+';
    		else st[i]=st[i+n]='*';
    	}
    	long long maxn=-(2<<30-1),ans=0;
    	for(long long i=1;i<=n;i++)
    	{
    		init();
    		long long cnt=0;
    		for(long long j=i;j<=i+n-1;j++) sz[++cnt]=a[j];
    		cnt=0;
    		for(long long j=i+1;j<=i+n-1;j++) str[++cnt]=st[j];
    		for(long long j=1;j<=n;j++) dp[j][j][0]=dp[j][j][1]=sz[j];
    		long long xx=dp_sry();
    		if(xx==maxn) sry[++ans]=i;
    		else if(xx>maxn) maxn=xx,ans=0,sry[++ans]=i;
    	}
    	cout<<maxn<<endl;
    	for(long long i=1;i<ans;i++) cout<<sry[i]<<" ";cout<<sry[ans];
    }
    • 1

    信息

    ID
    180
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者