Luogu P4342 Polygon 题解报告

题目传送门

【题目大意】

给一个n边形,每个顶点上有一个数值,每条边上有一个运算符号。每次删去一条边,同时将这条边连接的两端点的数值进行运算(运算符号记为这条边上的符号),求删去所有边后的最大值。

【思路分析】

首先断环为链,然后就跟石子合并是差不多的了,不过因为涉及到乘法并且有负数,所以DP过程中除了记录最大值还要记录最小值,详见代码。

【代码实现】

 1 #include<cstdio>
 2 #include<iostream>
 3 #define rg register
 4 #define go(i,a,b) for(rg int i=a;i<=b;i++)
 5 using namespace std;
 6 const int N=102;
 7 const int INF=1e9+9;
 8 int n,m,a[N],f[N][N],g[N][N],ans=-INF;
 9 char b[N];
10 int main(){
11     scanf("%d",&n);m=n<<1;
12     go(i,1,n) {cin>>b[i]>>a[i];b[i+n]=b[i];a[i+n]=a[i];}
13     go(i,1,m) go(j,1,m) f[i][j]=-INF,g[i][j]=INF;
14     go(i,1,m) f[i][i]=g[i][i]=a[i];
15     go(len,2,n)
16         go(l,1,m-len+1)
17     {
18         int r=l+len-1;
19         go(mid,l,r-1)
20         {
21             if(b[mid+1]=='t')
22             {
23                 f[l][r]=max(f[l][r],f[l][mid]+f[mid+1][r]);
24                 g[l][r]=min(g[l][r],g[l][mid]+g[mid+1][r]);
25             }
26             else
27             {
28                 f[l][r]=max(f[l][r],max(f[l][mid]*f[mid+1][r],max(f[l][mid]*g[mid+1][r],max(g[l][mid]*f[mid+1][r],g[l][mid]*g[mid+1][r]))));
29                 g[l][r]=min(g[l][r],min(f[l][mid]*f[mid+1][r],min(f[l][mid]*g[mid+1][r],min(g[l][mid]*f[mid+1][r],g[l][mid]*g[mid+1][r]))));
30             }
31         }
32     }
33     go(i,1,n) ans=max(ans,f[i][i+n-1]);
34     printf("%d
",ans);
35     go(i,1,n) if(f[i][i+n-1]==ans) printf("%d ",i);
36     return 0;
37 }
代码戳这里
原文地址:https://www.cnblogs.com/THWZF/p/10997896.html