多边形游戏(DP)

题目描述

“多边形游戏”是一款单人益智游戏。

游戏开始时,给定玩家一个具有 N 个顶点 N 条边(编号 1∼N)的多边形,如图 1 所示,其中 N=4。 每个顶点上写有一个整数,每个边上标有一个运算符 +(加号)或运算符 *(乘号)。

在这里插入图片描述

第一步,玩家选择一条边,将它删除。

接下来在进行 N−1 步,在每一步中,玩家选择一条边,把这条边以及该边连接的两个顶点用一个新的顶点代替,新顶点上的整数值等于删去的两个顶点上的数按照删去的边上标有的符号进行计算得到的结果。

下面是用图 1给出的四边形进行游戏的全过程。

在这里插入图片描述
最终,游戏仅剩一个顶点,顶点上的数值就是玩家的得分,上图玩家得分为 0。
请计算对于给定的 N 边形,玩家最高能获得多少分,以及第一步有哪些策略可以使玩家获得最高得分。

输入描述

输入包含两行,第一行为整数 N。

第二行用来描述多边形所有边上的符号以及所有顶点上的整数,从编号为 1的边开始,边、点、边…按顺序描述。
其中描述顶点即为输入顶点上的整数,描述边即为输入边上的符号,其中加号用 t 表示,乘号用 x 表示。

输出描述

输出包含两行,第一行输出最高分数。

在第二行,将满足得到最高分数的情况下,所有的可以在第一步删除的边的编号从小到大输出,数据之间用空格隔开。

数据范围

3≤N≤50,
数据保证无论玩家如何操作,顶点上的数值均在 [−32768,32767] 之内。

Sample Input

4
t -7 t 4 x 2 x 5

Sample Output:

33
1 2 

具体代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string.h>
using namespace std;
const int M = 51,inf=32768;
int v[M];
char op[M];
int m[M][M][2];
int n;
int minf;
int maxf;
void minMax(int i,int s,int j)
{
	
	int e[5];
	int a = m[i][s][0];//i-到i+s的最小值
	int b = m[i][s][1];//i到i+s的最大值
	int r = (i + s - 1) % n + 1;
	int c = m[r][j - s][0];//i+s到j的最小值
	int d = m[r][j - s][1];//i+s到j的最大值
	if (op[r] == 't')
	{
		minf = a + c;
		maxf = b + d;
	}
	if (op[r] == 'x')
	{
		e[1] = a * c;
		e[2] = a * d;
		e[3] = b * c;
		e[4] = b * d;
		sort(e + 1, e + 5);
		minf = e[1];
		maxf = e[4];
	}	
}
int polyMax()
{
	for (int j = 1; j <= n; j++)
	{
		for (int i = 1; i <= n; i++)
		{
			if (j == 1)
			{
				m[i][j][0] = v[i];
				m[i][j][1] = v[i];
				//printf("%d %d\n", m[i][j][0], m[i][j][1]);
			}
			else {
				m[i][j][0] = inf;
				m[i][j][1] = -inf;
			}
			for (int s = 1; s <j; s++)
			{
				minMax(i, s, j);
				//if (i == 1 && j == 2)
				//{
					//printf("%d %d\n", minf, maxf);
				//}
				if (m[i][j][0] > minf)
					m[i][j][0]=minf;
				if (m[i][j][1] < maxf)
					m[i][j][1] = maxf;
				//printf("i=%d j=%d %d %d\n",i,j, m[i][j][0], m[i][j][1]);
			}
		}
	}
	int t = m[1][n][1];
	//cout<<t;
	for (int i = 2; i <= n; i++)
		if (t < m[i][n][1])
			t = m[i][n][1];
	return t;
}
int main()
{
	//int n;
	scanf("%d", &n);
	int h = 1;
	getchar();
	for (int i = 1; i <= n; i++)
	{
		if (h % 2 == 1)
		{
			scanf("%c", &op[i]);
			h++;
		}
		if (h % 2 == 0)
		{
			scanf("%d", &v[i]);
			getchar();
			h++;
		}
	}
	int t = polyMax();
	cout <<t<< endl;
	//cout << m[1][n][1];
	for (int i = 1; i <= n; i++)
		if (m[i][n][1] == t)
			cout << i << ' ';
	return 0;
}

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值