对于这道题前面的处理过程有些许抽象所以我们先说前面的处理数据过程,我们对于每一条边我们都要进行枚举,作为我们要去掉的边,所以我们要采取一个动态的办法,在去掉当前边时,我们将剩下的边和点赋给两个新数组,用于确定循环数组的顺序。
我们的处理过程如下
char zh=op1[edge];//这里我们要将这个要去掉的边暂时保留,用于之后我们重新还给原来的数组 op1[edge]='/';//说明当前边暂时没了 int t=0;//这个是用来移动的标准,如果遍历到了当前枚举的符号就变为1,用于之后的移动 for(int i=0;i<num;i++)//其中的num2数组和op2数组是用来进行数组顺序的判定的 { num2[i]=num1[(edge+i)%num]; if(i==n-1)continue; if(op1[(edge+i)%num])t=1; op2[i]=op1[(edge+i+t)%num]; }
然后我们看看规律:
我们这里会发现我们的edge可以当作一个作为赋值的起点。这样我们就根据以上规律得到了正确的循环顺序。
我们之后分析该题。
这是不是我们的矩阵链问题了呢。
所以我们在看其矩阵
最后我们发现其和矩阵链相乘简直一模一样。
所以我们也有两种方法。
//方法一
#include<bits/stdc++.h>
using namespace std;
int num1[100];
int num2[100];
char op1[100];
char op2[100];
int dp[100][100];
int maxs[100];
int counts(int x,int y,char z)
{
if(z=='t')return x+y;
else if(z=='x')return x*y;
}
int main()
{
int num;cin>>num;
for(int i=0;i<num;i++)cin>>op1[i]>>num1[i];
int n=num;
for(int edge=0;edge<n;edge++)
{
char zh=op1[edge];
op1[edge]='/';
int t=1;
for(int i=0;i<num;i++)//确定多边形的循环的顺序,意思就从哪开始
{
num2[i]=num1[(edge+i)%num];
if(i==n-1)continue;
op2[i]=op1[(edge+i+t)%num];
}
memset(dp,0,sizeof(dp));
for(int i=0;i<num;i++)dp[i][i]=num2[i];
for(int r=1;r<n;r++)//这是我们的最大括数
{
for(int i=0;i<n;i++)
{
int j=i+r;
for(int k=i;k<j;k++)
{
dp[i][j]=max(dp[i][j],counts(dp[i][k],dp[k+1][j],op2[k]));
}
}
}
op1[edge]=zh;
maxs[edge]=dp[0][num-1];
}
int maxn=0;
for(int i=0;i<num;i++)
{
maxn=max(maxs[i],maxn);
}
cout<<maxn<<endl;
for(int i=0;i<num;i++)
{
if(maxn==maxs[i])
{
cout<<i+1<<" ";
}
}
}
//方法二
#include<bits/stdc++.h>
using namespace std;
int num1[100];
int num2[100];
char op1[100];
char op2[100];
int dp[100][100];
int maxs[100];
int counts(int x,int y,char z)
{
if(z=='t')return x+y;
else if(z=='x')return x*y;
}
int main()
{
int num;cin>>num;
for(int i=0;i<num;i++)cin>>op1[i]>>num1[i];
int n=num;
for(int edge=0;edge<n;edge++)
{
char zh=op1[edge];
op1[edge]='/';
int t=1;
for(int i=0;i<num;i++)//确定多边形的循环的顺序,意思就从哪开始
{
num2[i]=num1[(edge+i)%num];
if(i==n-1)continue;
op2[i]=op1[(edge+i+t)%num];
}
memset(dp,0,sizeof(dp));
for(int i=0;i<num;i++)dp[i][i]=num2[i];
for(int i=num-1;i>=0;i--)//从对角线开始
{
for(int j=i+1;j<num;j++)
{
for(int k=i;k<=j;k++)
{
dp[i][j]=max(dp[i][j],counts(dp[i][k],dp[k+1][j],op2[k]));
}
}
}
op1[edge]=zh;
maxs[edge]=dp[0][num-1];
}
int maxn=0;
for(int i=0;i<num;i++)
{
maxn=max(maxs[i],maxn);
}
cout<<maxn<<endl;
for(int i=0;i<num;i++)
{
if(maxn==maxs[i])
{
cout<<i+1<<" ";
}
}
}