问题说明
开始时一个由n个顶点构成的多边形。每个顶点被赋予一个整数值,每条边被赋予一个运算符“+”或“ × ”。所有边依次用整数从1到n编号。之后,将相邻两个顶点的数值按照两数之间的边对应的运算符进行运算,然后删掉这条边,两个顶点合称为一个顶点,这个新顶点上的数就是上面运算的结果。直到最后所有边都被删除,剩下一个顶点,顶点上的数就是多边形游戏得分。
问题分析
n边形我们可以看成是一个首尾相连的圆,当然就可以使用循环链表实现了,但是这样一来就太麻烦了。对于这个问题,当我们选中一个点作为起点之后,我们不需要考虑终点与起点在劣弧上的运算,大家简单推演一遍就知道了。因此,我们可以把这个问题看作是n个链表,n个点分别做链表的头节点。
我们设点数组为V[7],边(运算符)数组为op[7],由于是从1开始编号,所以我们空出0编号位置,于是可以华看作下面n个链表。我们先把这个例子放在一边,我们还得解决一个问题。
这里我们在考虑一个问题。设二维数组m[i][j]表示从V[i]开始含有j个节点的链。根据动态规划,我们假设最后一次运算发生在op[i+s],其左右两边已经计算出最优值,则有链
由于存在负数和乘法,不能简单地将最大值作为某链(或者支链)的最优值,根据乘法的性质,我们可以算出左右两边的最大值和最小值,两两进行运算,则会有四种规划。这是我们将上面设的数组m改进为m[i][j][1] 或者 m[i][j][0],分别表示表示从V[i]开始含有j个节点的链的最小值和最大值。设左边支链的最大值最小值为a、b,右边支链的最小值和最大值为c、d则
s为m[i][j][1] 中假设的最后一次运算位置,根据定义可以知道 s∈[1,j-1],于是我们得到:
给出初始值:m[i][1][0]=m[i][1][1]=V[i]
关键代码
public class PolygonGame {
private int []V = new int[]{
0,-3,-4,5,7,-1,6}; //编号为0的用不到,于是我们随便赋值
private char []op = new char[]{
' '