问题
多边形游戏是一个单人玩的游戏,开始时有一个由n个顶点构 成的多边形。每个顶点被赋予一个整数值,每条边被赋予一个 运算符“+”或“*”。所有边依次用整数从1到n编号。
游戏第1步,将一条边删除。 随后n-1步按以下方式操作: (1)选择一条边E以及由E连接着的2个顶点V1和V2;
(2)用一个新的顶点取代边E以及由E连接着的2个顶点V1和V2。 将由顶点V1和V2的整数值通过边E上的运算得到的结果赋予新 顶点。E
最后,所有边都被删除,游戏结束。游戏的得分就是所剩顶 点上的整数值。
问题:对于给定的多边形,计算最高得分。
以此图举例
我们先断边1,那么524+(-7)=33最大
我们断边2,那么425+(-7)=33最大
我们断边3,那么25+(-7)+4=7最大
我们断边4,那么24+(-7)+5=6最大
这里面最大的值为33
思路
我们可以用一个数组储存断不同边得到的值
过程:
断掉一条链可以将原链分为两条链,通过求两条链的最值,再将通过断掉链的操作符进行操作,即
断掉一条边后分为了两条链,用四个数记录两条链的最大值与最小值(注意这里记录最小值是由于断掉的链的操作符可能为乘,而出现负负得正的情况),即划分、合并过程。
递归边界就是只剩下两个操作数与一个操作符,此时我们能得到最大最小值,重要的是我们要去遍历断链的位置,计算第一次端哪条链可得到总体最大值。
代码实现
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 100
int n,v[N],m[N][N][2];
char op[N];
void MinMax(int n,int i,int k,int j,int &minf,int &maxf){//最大值和最小值
int e[5],r;
int a=m[i][k][0],b=m[i][k][1];//a是前段链最小值,b是最大值
r=(i+k-1)%n+1;//因为是循环可取余来做
int c=m[r][j-k][0],d=m[r][j-k][1];//c是后段链最小值,d是最大值
if(op[k-1]=='+'){//加的话,最小相加即最小,最大相加即最大
minf=a+c;
maxf=b+d;
}else{//乘可能会出现负负得正的情况,所以需要考虑四种情况
e[1]=a*c;
e[2]=a*d;
e[3]=b*c;
e[4]=b*d;
minf=e[1];
maxf=e[1];
for(int t=2;t<=4;t++){//遍历寻找最大最小
if(maxf<e[t]){
maxf=e[t];
}
if(minf>e[t]){
minf=e[t];
}
}
}
}
int main()
{
int i,j,k,minf,maxf;
printf("请输入多边形顶点数:");
scanf("%d",&n);
for(i=1;i<=n;i++){
printf("请输入%d边的操作数和运算符:",i);
scanf("%d %c",&v[i],&op[i]);
m[i][1][0]=v[i];
m[i][1][1]=v[i];
}
for(j=2;j<=n;j++){
for(i=1;i<=n;i++){//删除的边
for(k=1;k<=j-1;k++){//断链位置
MinMax(n,i,k,j,minf,maxf);
if(m[i][j][0]>minf){
m[i][j][0]=minf;
}
if(m[i][j][1]<maxf){
m[i][j][1]=maxf;
}
}
}
}
int temp=m[1][n][1],p=1;
for(i=2;i<=n;i++){
if(m[i][n][1]>temp){
temp=m[i][n][1];
p=i;
}
}
printf("首断链位置为:%d,最大得分为:%d\n",p,temp);
return 0;
}