问题描述:
多边形游戏是一个单人玩的游戏,开始时有一个由n个顶点构成的多边形。每个顶点被赋予一个整数值,每条边被赋予一个运算符“+”或“*”。所有边依次用整数从1到n编号。
游戏第1步,将一条边删除。
随后n-1步按以下方式操作:
(1)选择一条边E以及由E连接着的2个顶点V1和V2;
(2)用一个新的顶点取代边E以及由E连接着的2个顶点V1和V2。将由顶点V1和V2的整数值通过边E上的运算得到的结果赋予新顶点。
最后,所有边都被删除,游戏结束。游戏的得分就是所剩顶点上的整数值。
问题:对于给定的多边形,计算最高得分。
如下图:
数据输入:
第一行是一个整数N
第二行按照
边 顶点 边 顶点 …. 边 顶点
的顺序以此存放了N个顶点和N条边的标注信息。
问题求解:
当把一条边去除除后,再把它拉直,那么这个问题就可以变成一条链。那么就和以前写的矩阵连乘有几分的相似,其实我们最后要求的是这个链的表达式算式结果的最大值。于是我们就可以想到可以用数组p[i][j]来表示从点i开始,链长为j的算术表达式的最大值,用v[i]存储操作数,op[i]存储操作符。如果这条链的最后一次合并运算在op[i+s]处发生(1≤s≤j-1),则可在op[i+s]处将链分割为2个子链p[i][s]和p[i+s][j-s]。似乎这样再按照以前解决动态规划题目时的思路,就可以解决问题了。 但是,我们再来考虑一下,由于有两种运算符+和x,并且操作数可能存在负数,那么我们也必须考虑两个负数相乘的结果可能比两个正数要打,所以我们同时还需要记录每个链的最大和最小值,然后判断,如果操作符为+的话,只需要两个链的最大值相加即可,如果操作符是x的话,那么必须把各种情况考虑进来,然后再求出最大值。分析如下:
(1)当op[i+s]='+'时,显然有a+c≤m≤b+d
(2)当op[i+s]='*'时,有min{ac,ad,bc,bd}≤m≤max{ac,ad,bc,bd}
如果看不懂上面,下面这个图形可能更好理解:
给出一个n个顶点的多边形,每个顶点是一个整数值, 每条边是运算符‘+’或‘*’,
第一步:将某个边断开,形成一条数值和符号组成的链
接下来的n-1步按以下方式操作:
(1)选择一条边及边连接的两个顶点v1,v2;
(2)用一个新的顶点代替上述边和顶点,其值为,v1,v2经中间的运算符运算后得到得数;
以n=7为例:
附上js代码:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> 多边形游戏-动态规划 </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<script>
var v=[1,2,3];//点;
var op=['+','+','x'];//对应边的操作符
var value=[];//备忘录 value[i][j][0] 起点为i,链长为j 最小值 value[i][j][1]为最大值
//初始化值
var len=v.length;
for(var i=0;i<len;i++){//起点,
value[i]=[];
for(var j=0;j<len;j++){//链长
value[i][j]=[];
if(j==0){
//链长为0,最大值,最小值均为顶点值
value[i][0][0]=v[i];
value[i][0][1]=v[i];
}else{
value[i][j][0]=99999;
value[i][j][1]=-99999;
}
}
}
//开始计算
for(var length=1;length<len;length++){//控制链长
for(var start=0;start<len;start++){
for(var k=0;k<length;k++){
getMax(start,length,k);
}
}
}
//输出结果(逐步去除某条边)
var maxValue=value[0][len-1][1];
for(var start=1;start<len;start++){
maxValue=Math.max(maxValue,value[start][len-1][1]);
}
document.write("最大值为:"+maxValue);
//拆分计算
function getMax(start,length,k){
var index=(start+k+1)%len;
var a=value[start][k][0];
var b=value[start][k][1];
var c=value[index][length-k-1][0];
var d=value[index][length-k-1][1];
// a<=m1<=b c<=m2<=d
document.write("value["+start+"]["+k+"];value["+index+"]["+(length-k-1)+"]<br/>");
document.write("a="+a+";b="+b+";c="+c+";d="+d+"<br/>");
var min=value[start][length][0];
var max=value[start][length][1];
//document.write("max="+max+";min="+min+"<br/>");
if(op[index]=="+"){
max=Math.max(max,b+d);
min=Math.min(min,a+c);
}
else if(op[index]=="x"){
max=Math.max(a*c,a*d,b*c,b*d);
min=Math.min(a*c,a*d,b*c,b*d);
}
value[start][length][0]=min;
value[start][length][1]=max;
document.write("value["+start+"]["+length+"];"+value[start][length]+"<br/>");
}
</script>
</HEAD>
<BODY>
</BODY>
</HTML>
运行结果:
value[0][0];value[1][0]
a=1;b=1;c=2;d=2
value[0][1];3,3
value[1][0];value[2][0]
a=2;b=2;c=3;d=3
value[1][1];6,6
value[2][0];value[0][0]
a=3;b=3;c=1;d=1
value[2][1];4,4
value[0][0];value[1][1]
a=1;b=1;c=6;d=6
value[0][2];7,7
value[0][1];value[2][0]
a=3;b=3;c=3;d=3
value[0][2];9,9
value[1][0];value[2][1]
a=2;b=2;c=4;d=4
value[1][2];8,8
value[1][1];value[0][0]
a=6;b=6;c=1;d=1
value[1][2];7,8
value[2][0];value[0][1]
a=3;b=3;c=3;d=3
value[2][2];6,6
value[2][1];value[1][0]
a=4;b=4;c=2;d=2
value[2][2];6,6
最大值为:9
本文文字部分参考了博客