游戏执行步骤:
游戏的第1步,将一条边删除。
随后的n-1步按以下方式操作:
①选择一条边E以及由E连接着的2个顶点V1和V2。
②用一个新的顶点取代边E以及由E连接着的2个顶点V1和V2。
③将由V1和V2的整数值通过边E上运算所得的结果赋予新顶点。
当所有边都被删除时,游戏结束,游戏的得分即为所剩顶点上的整数值。
最优子结构性质:
设所给的多边形的顶点和边的顺时针序列为:op[1],v[1],op[2],v[2],...,op[n],v[n],其中op[i]表示第i条边所对应的运算符,v[i]表示第i个顶点上的数值(1<=i<=n)。从顶点i(1<=i<=n)开始,长度为j(链中有j个顶点)的顺时针链p(i,j)可表示为:v[i],op[i+1],...,v[i+j-1]。
若这条链p(i,j)的最后一次合并运算在op[i+s](1<=s<=j-1)处,则在op[i+s]处将链分割为两个子链p(i,s)和p(i+s,j-s)。设m1是对子链p(i,s)的任意一种合并方式得到的值,a和b分别所有合并中的最小值和最大值;m2是p(i+s,j-1)的任意一种合并方式得到的值,c和d分别是所有合并中的最大值和最小值;故a<=m1<=b,c<=m2<=d。m=m1 op[i+s] m2是两条子链合并的值;当op[i+s]=’+’时,a+b<=m<=b+d;当op[i+s]=’*’时,由于v[i]可取负数,故min{ac,ad,bc,bd}<=m<=max{ac,ad,bc,bd};所以主链的最大和最小值可由子链的最大和最小值得到。
计算最优值:
设m[i,j,0]是链p(i,j)合并的最小值,m[i,j,1]是最大值。若最优合并在op[i+s]处将p(i,j)分为2个子链p(i,s)和p(i+s,j-s),a=m[i,s,0],b=m[i,s,1],c=m[i+s,j-s,0],d=m[i+s,j-s,1]。
当op[i+s]=’+’时,m[i,j,0]=a+c,m[i,j,1]=b+d;当op[i+s]=’*’,m[i,j,0]=min{ac,ad,bc,bd},m[i,j,1]=max{ac,ad,bc,bd}。
int polygonGame(int v[],char op[],int n){
int m[n+1][n+1][2];
int minf[n+1][n+1][n];
int maxf[n+1][n+1][n];
for(int e=0;e
for(int f=0;f
for(int g=0;g<2;g++){
m[e][f][g]=0;
}
}
}
for(int i=1;i<=n;i++){ //当只有一个顶点时,最大最小值都为该顶点的值
m[i][1][0]=v[i];
m[i][1][1]=v[i];
}
for(int j=2;j<=n;j++){ //j表示链长
for(int i=1;i<=n;i++){ //i表示首次删除的边的序号
int min,max; //链从s处断开的最大值与最小值
for(int s=1;s<=j-1;s++){ //s表示链p(i,j)断开的位置
int k=(i+s-1)%n+1; //i+s有可能会超过n,要回绕
int a=m[i][s][0];
int b=m[i][s][1];
int c=m[k][j-s][0];
int d=m[k][j-s][1];
if(op[k]=='+'){
minf[i][j][s]=a+c;
maxf[i][j][s]=b+d;
}
else{
int array[4]={a*c,a*d,b*c,b*d};
minf[i][j][s]=array[0];maxf[i][j][s]=array[0];
for(int m=1;m<4;m++){
if(minf[i][j][s]>array[m])
minf[i][j][s]=array[m];
if(maxf[i][j][s]
maxf[i][j][s]=array[m];
}
}
min=minf[i][j][s];max=maxf[i][j][s];
}
if(m[i][j][0]>min) //找出当i一定,s变化时的最大最小值
m[i][j][0]=min;
if(m[i][j][1]
m[i][j][1]=max;
}
}
int count=m[1][n][1];
for(int i=2;i
if(count
count=m[i][n][1];
}
}
return count;
}