多边形游戏

【题目描述】
lqp家离学校十分十分远,没有人陪他玩,于是他只好自娱自乐了……
有这么一个N个顶点的多边形,每个顶点上标上一个数字,每条边上有一个运算符号+或者*,边从1到N编号。
游戏的规则是这样的:先去掉一条边,然后这样:每次选一条边e,它的两个端点是v1和v2,用一个新的顶点取代,顶点上的数是这两个数按e操作的结果。当只剩一个点的时候,游戏结束,得分就是你最后达到的那个数。
lqp很喜欢这个游戏,但是他不知道自己玩得如何,于是他想问你一个局面可以得到的最高分是多少,这样他好知道自己每次玩得如何。
【输入格式】
输入描述N个顶点。有两行,第一行是N(3<=N<=20),第2行按顺序给出运算符和数字,中间全都用一个空格隔开。
【输出格式】
最高得分。
【样例输入】
4
+ -7 + 4 * 2 * 5
【样例输出】
33
【分析】
首先理解下样例:

如图,4*2*5-7=33。
设num[i]存放多边形顶点的数,op[i]存放多边形边上的运算符,f[i][j][0..1]存放合并点i到点j的最小值和最大值。
考虑多边形的最后一次合并,令其发生在点i+x处则可以将链(i,j)分割成(i,x)和(i+x,j-x)两段,我们可以将两个子链的最大值和最小值算出来,存在四个变量a,b,c,d中。
注意:i+x的值可能超过n,需要取模!
此时对op[i+x]分类讨论:
当op[i+x]为加号时,e=a+b,i=c+b,g=a+d,h=c+d;
当op[i+x]为乘号时,e=a*b,i=c*b,g=a*d,h=c*d.
最后计算f[i][j][0..1]的值即可。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
bool flag;
int n;
LL num[55],f[55][55][2],ans;
char op[55];
int main(){
    scanf("%d",&n);
    for (int i=1;i<=n;i++){
        scanf("%s",op+i);
        if (i==n) cin>>num[1]; else cin>>num[i+1];
        num[i+1+n]=num[n];
    }
    for (int i=1;i<=n;i++) f[i][0][0]=num[i],f[i][0][1]=num[i];
    for (int y=1;y<n;y++)
      for (int x=1;x<=n;x++){
            bool use1=0,use2=0;
            for (int z=0;z<y;z++){
                int r=x+z+1;
                if (r>n) r%=n;
                LL a=f[x][z][0],b=f[r][y-z-1][0],c=f[x][z][1],d=f[r][y-z-1][1],e,i,g,h;
                int j=x+z;
                if (j>n) j%=n;
                if (op[j]=='+') e=a+b,i=c+b,g=a+d,h=c+d; else e=a*b,i=c*b,g=a*d,h=c*d;
                LL minn=min(min(e,i),min(g,h)),maxn=max(max(e,i),max(g,h));
                if (use1==0) use1=1,f[x][y][0]=minn; else f[x][y][0]=min(f[x][y][0], minn);
                if (use2==0) use2=1,f[x][y][1]=maxn; else f[x][y][1]=max(f[x][y][1],maxn);
            }
            use1=0,use2=0;
            if (y==n-1)
                if (flag==0) flag=1,ans=f[x][y][1]; else ans=max(ans,f[x][y][1]);
        }
    cout<<ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值