多边形游戏(二维数组+动态)

题目:

本题目给出一个N个顶点的多边形,每个顶点标记一个数字表示该点的值,每条边标记“+”表示加法或标记“*”表示乘法,这些边从1到N编号。图一所示为一个N=4的多边形。
在这里插入图片描述
游戏规则:
1.首先去掉一条边。
2.选择一条边E和与E边相连的两个顶点V1、V2,用一个新顶点来替换它们,新顶点的值为边E上标记的运算符对V1和V2上的值进行运算的结果。
3. 重复步骤2,直到只剩下一个顶点为止,这个顶点上的值即为游戏得分。
在这里插入图片描述

输入格式:

输入数据有两行,第一行是数字N(3 <= N <= 50),第二行是交叉地给出边上的运算符(字母t表示加法,字母x表示乘法)和顶点的值,以空格分隔。

输出格式:

第一行输出最大得分。
第二行输出游戏第一步移除哪条边可能使得结果分数最高,如果有多种可能则全部输出,每个数字后面有一个空格。

输入样例:

该样例同图示例子,第一行表示N=4,第二行表示第一条边上符号为加法,第一条边和第二条边中间的顶点值为-7,第二条边上符号为加法,第二条边和第三条边中间的顶点值为4,以此类推。

4
t -7 t 4 x 2 x 5
结尾无空行

输出样例:

33
1 2
结尾无空行

解题思路:

本题属于动态规划,最核心的思路是矩阵连乘思想。题中要求寻得如何断环为链,以及断后如何结合运算才能取得最大值。和矩阵如何加括号运算很相似。

1.预备工作 设定一个sum数组,用于存储断第i条边后,针对此链运算的最大值。
num1,op1是用来存储最原始的数字和操作符信息,num2,op2是针对断某条边的改过顺序的操作数和操作符。
2.对每一条链子进行如下操作:
寻找最佳结合方式,状态转移方程如下,取整条链子结合的最大值m[0][n-1]作为这条链子(断这条边后结合)的值,即sum[edge]=m[0][n-1];
3.在sum数组选最值即可。

状态转移

 m[i][j]=max ( m[i][j] , am(m[i][k], m[k+1][j] , op2[k]) ); 
 //am函数表示将 m[i][k] 和 m[k+1][j] 进行 op2[k] 操作。
 //即在i-j之间取断点k,前后两部分进行+或*操作后与原m[i][j]比较,取大值。

断掉每一条边的运算情况:
断掉每一条边的运算顺序

代码:

#include<bits/stdc++.h>
using namespace std;
int am(int x,int y,char op)//add or multipuly
{
	if(op=='t')return x+y;
	else if(op=='x')return x*y;
}
int main()
{
	int n;
	int sum[100];//记录删掉边的最大结合值
	int num1[100];//记录初始数据
	int num2[100];//针对某一条去掉的边的数据
	char op1[100];//记录初始数据
	char op2[100];//针对某一条去掉的边的数据
	int m[100][100];//记录状态
	cin>>n;
	cin.get();

//	getline(cin,str);
//	for(int i=0;i<str.size();i++)
//	{
//		if(str[i]=='t'||str[i]=='x')op1[temp1++]=str[i];
//		if(str[i]>='0'&&str[i]<='9')
//		{
//			int number=0,j;
//			for(j=i;;j++)
//			{
//				if(str[j]<'0'||str[j]>'9')break;
//				number=number*10+str[j]-'0';				
//			}
//			if(str[i-1]=='-')number*=-1; 
//			num1[temp2++]=number;
//			i=j;
//		}
//	}
	for(int i=0;i<n;i++)	cin>>op1[i]>>num1[i]; //数据组数是确定的,直接一组一组输入操作符和运算数即可,上面的是未知组数的输入办法
	for(int edge=0;edge<n;edge++)//讨论第i条边 
	{
		char ch=op1[edge];
		op1[edge]='/'; //将这条边上的运算符暂时抹去,但是记得用完了恢复。
		int t=0;
		for(int i=0;i<n;i++)//这个循环是求出某一边断后的运算数和运算符的顺序
		{
			num2[i]=num1[(edge+i)%n];
			if(i==n-1)continue;
			if(op1[(edge+i)%n]=='/')t=1;//为了弃掉抹去了的运算符,后面的符号都移一个就行了
			op2[i]=op1[(edge+i+t)%n];
		}
		
		memset(m,0,sizeof(m));//每条边运算的m都不一样,所以每次在使用前都需要初始化,这里初始为0.
		for(int i=0;i<n;i++)m[i][i]=num2[i]; 
		for(int r=1;r<n;r++)//标准的矩阵结合三个循环的思想。
		{
			for(int i=0;i<n-r;i++)
			{
				int j=i+r;
				for(int k=i;k<j;k++)
				{
					m[i][j]=max(m[i][j],am(m[i][k],m[k+1][j],op2[k])); 
				}
			}
		}
		sum[edge]=m[0][n-1];
		op1[edge]=ch;//恢复边
	}
	int max=0;
	for(int i=0;i<n;i++)
	{
		if(sum[i]>sum[max])max=i;
	}
	cout<<sum[max]<<endl;
	for(int i=0;i<n;i++)
	{
		if(sum[i]==sum[max])cout<<i+1<<" ";
	}
	return 0;
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的多边形游戏的C代码示例,其中包括绘制多边形和检测多边形是否被点击: ```c #include <stdio.h> #include <graphics.h> #define MAX_POINTS 50 // 定义一个结构体来存储多边形的点 typedef struct { int x; int y; } point_t; // 绘制多边形 void draw_polygon(point_t points[], int num_points) { int i; for (i = 0; i < num_points; i++) { line(points[i].x, points[i].y, points[(i+1)%num_points].x, points[(i+1)%num_points].y); } } // 检测多边形是否被点击 int is_polygon_clicked(point_t points[], int num_points, int x, int y) { int i, j; int c = 0; for (i = 0, j = num_points-1; i < num_points; j = i++) { if (((points[i].y > y) != (points[j].y > y)) && (x < (points[j].x - points[i].x) * (y - points[i].y) / (points[j].y - points[i].y) + points[i].x)) { c = !c; } } return c; } int main() { int gd = DETECT, gm; initgraph(&gd, &gm, ""); point_t points[MAX_POINTS]; int num_points = 0; int i = 0; // 从用户输入中获取多边形点的数量和坐标 printf("Enter the number of points in the polygon: "); scanf("%d", &num_points); printf("Enter the coordinates of each point:\n"); for (i = 0; i < num_points; i++) { printf("Point %d: ", i+1); scanf("%d %d", &points[i].x, &points[i].y); } // 绘制多边形 draw_polygon(points, num_points); // 检测是否被点击 int x, y; while (!kbhit()) { if (ismouseclick(WM_LBUTTONDOWN)) { getmouseclick(WM_LBUTTONDOWN, x, y); if (is_polygon_clicked(points, num_points, x, y)) { printf("The polygon was clicked!\n"); } else { printf("The polygon was not clicked.\n"); } } } closegraph(); return 0; } ``` 注意,以上代码使用了graphics.h库,因此需要在编译时使用-lgraphics参数。例如,对于gcc编译器,可以使用以下命令来编译代码: ```shell gcc -o polygon_game polygon_game.c -lgraphics ``` 请确保你的编译环境中已经安装了graphics.h库。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值