算法设计——多边形游戏(动态规划)

问题

多边形游戏是一个单人玩的游戏,开始时有一个由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,那么2
4+(-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;
}

结果检验

在这里插入图片描述

  • 12
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值