多边形游戏问题

来源:互联网 发布:晨曦软件视频教程 编辑:程序博客网 时间:2024/06/06 19:45

问题描述:

 多边形游戏是一个单人玩的游戏,开始时有一个由n个顶点构成的多边形。每个顶点被赋予一个整数值,每条边被赋予一个运算符“+”或“*”。所有边依次用整数从1到n编号。

  游戏第1步,将一条边删除。

  随后n-1步按以下方式操作:

  (1)选择一条边E以及由E连接着的2个顶点V1和V2;

  (2)用一个新的顶点取代边E以及由E连接着的2个顶点V1和V2。将由顶点V1和V2的整数值通过边E上的运算得到的结果赋予新顶点。

  最后,所有边都被删除,游戏结束。游戏的得分就是所剩顶点上的整数值。

  问题:对于给定的多边形,计算最高得分。

如下图:

  

解:

设所给的多边形的顶点和边的顺时针序列位

op[1], v[1], op[2], v[2]...,op[n], v[n],其中op代表存储操作符的第i条边,v为存储顶点数值的数组。

设p[i][j]为存储以i节点为起点,长度为j的链的运算结果最小值数组,则可知p[i][n]为多边形第i边断裂后形成的链的最高分值结果。假设在op[i+s]处发生了合并运算,则可以在op[i+s]处将链分割成两个子链p[i][s],和p[i+s][j-s]两条子链,这也是链结果运算的最优子结构。

对于操作符,当op[i+s]为+时,最高得分为两子链之和;当op[i+s]为*时,因为节点的赋值可以为整数,则我们要知道左右子链的最大最小值,分别相乘结果取到最大。

综上,多边形游戏问题满足最优子结构性质,是动态规划问题。

#include<iostream>#include<cstdlib>#define MAAX 1000#define MIIN -1000using namespace std;int p;int dot[MAAX];//多边形顶点的数值 数组 char op[MAAX];//多边形边的操作符号数组 int m[MAAX][MAAX][2];//第i个顶点/长度为j时/1最大0最小值 的 存储 void minMax(int i, int s, int j);int polyMax(int num); int main(){int num, ans; printf("输入多边形顶点数:");cin>>num;cout<<"输入顶点值和边的类型";for(int i=1; i<=num; i++){cout<<"第"<<i<<"点:";cin>>dot[i];cout<<"第"<<i<<"边:";cin>>op[i]; }for(int i=1; i<=num; i++){for(int j=1; j<=num; j++){m[i][j][0] = MAAX;m[i][j][1] = MIIN;}}for(int i=1; i<=num; i++)//长度为1时,链为单个节点,则值为节点本身权值 {m[i][1][0] = dot[i];m[i][1][1] = dot[i];}ans = polyMax(num);cout<<"最高得分为"<<ans<<endl; cout<<"首次删除"<<p<<"边"<<endl; return 0; }   void minMax(int i, int s, int j, int num) { int minf, maxf; int a = m[i][s][0]; int b = m[i][s][1]; int r = (i+s-1)%num +1; int c = m[r][j-s][0]; int d = m[r][j-s][1]; int e[5]; if(op[r]=='+')//读到边操作符+时  { minf = a+c; maxf = b+d; if(m[i][j][0]>minf)m[i][j][0] = minf;if(m[i][j][1]<maxf)m[i][j][1] = maxf; }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 k=1; k<=4; k++){if(minf>e[k])minf = e[k];if(maxf<e[k])maxf = e[k];}if(m[i][j][0]>minf)m[i][j][0] = minf;if(m[i][j][1]<maxf)m[i][j][1] = maxf;} }  int polyMax(int num) { for(int length = 2; length<=num; length++) { for(int i = 1; i<=num; i++) { for(int s = 1; s<length; s++)//i+s处的边断开  { minMax(i, s, length, num); } } } int temp = MIIN; p=1; for(int i=1; i<=num; i++) { if(temp<m[i][num][1]) { temp = m[i][num][1]; p=i; }  cout<<temp<<endl; }  return temp; }  


原创粉丝点击