矩阵链相乘问题及相关问题讲解三(多边形游戏)

 对于这道题前面的处理过程有些许抽象所以我们先说前面的处理数据过程,我们对于每一条边我们都要进行枚举,作为我们要去掉的边,所以我们要采取一个动态的办法,在去掉当前边时,我们将剩下的边和点赋给两个新数组,用于确定循环数组的顺序。

我们的处理过程如下

        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<<" ";
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

B程洪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值