1 条题解
-
0
这道题很有意思,也比较有难度,是一个算式形式的动态规划,和区间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
- 上传者