Dynamic Planning - Example 6. Polygon Game

1. Title Description

A Polygon game is a one-player game that starts with a polygon with n vertices. Each vertex is assigned an integer value, and each edge is assigned an operator'+'or'*'. All edges are numbered from 1 to n using integers in turn.

Step 1 of the game, delete an edge.
Then step n-1 operates as follows:
(1) Select an edge E and two vertices V 1 and V2 connected by E;
(2) Replace edge E with a new vertex and the two vertices V1 and V2 connected by E. The integer values from vertices V1 and V2 are assigned to the new vertices by operations on edge E.

Finally, all edges were removed and the game ended. The game's score is an integer on the remaining vertices.
Question: For a given polygon, the highest score is calculated.

Example:

2. Solving problems

1. Optimal Substructure Properties

In the given polygon, a clockwise chain p(i, j) of length J (with J vertices i n the chain) starting from vertex i(1 < I < n) can be represented as v[i], op[i+1],..., v[i+j-1].
If the last merge operation of the chain occurs at op[i+s] (1 < s < j-1), the chain can be divided into two subchains p(i, s) and p(i+s, j-s) at op[i+s].
--Examples

Set m1 to be the value obtained by any combination of subchains p(i, s), while a and b are the minimum and maximum values obtained from all possible combinations, respectively.
m2 i s the value of any combination of p(i+s, j-s), while c and d are the minimum and maximum values of all possible combinations, respectively.
a < m1 < b and c < m2 < d are defined accordingly

  • When op[i+s]='+', it i s evident that a+c < m < b+d
  • min{ac, ad, bc, bd} i s less than or equal to m ax{ac, ad, bc, bd} when op[i+s]='*'

In other words, the maximum and minimum values of the main chain can be derived from the maximum and minimum values of the subchains.

2. Recursive Solution

From the previous analysis, we can see that in order to get the maximum value of chain merging, the maximum and minimum values of chain merging must be found at the same time.
Set m[i,j,0] to be the minimum value for chain p(i,j) merging and m[i,j,1] to be the maximum value.
If the optimal merge divides p(i,j) into two subchains p(i,s) and p(i+s, j-s) with lengths less than j at op[i+s] (both s and J-s represent lengths)
For narrative convenience, note a=m[i, s,0], b=m[i, s,1], c=m[i+s,j-s,0], d=m[i+s,j-s,0]

  • When op[i+s]='+', m[i,j,0]=a+c, m[i,j,1]=b+d
  • When op[i+s]='*', m[i,j,0]=min{ac,ad,bc,bd}, m[i,j,1]=max{ac,ad,bc,bd}

Combining the above two points, the maximum value of p(i,j) disconnected at op[i+s] i s maxf(i,j,s) and the minimum value i s minf(i,j,s). Then:

Since there is a possibility that the length of the subchain s is 1 <= s <= J-1 (as long as it is guaranteed to be less than the original chain length j), it can be seen that: (Note: here should be 1<= s <= j-1)

The initial boundary values are obviously m[i,1,0]=v[i], m[i,1,1]=v[i], 1 < i< n.

The code is as follows:

// //Polygon Game
#include<bits/stdc++.h>
using namespace std;
#define NMAX 100
int N, m[NMAX+1][NMAX+1][2], v[NMAX+1];  //m[i][j][0], starting vertex is i, number of vertices is j (chain length)
char op[NMAX+1];
int k[NMAX+1][NMAX+1][2];  //Represents the first partition position of p(i, j), i.e. where the vertex is I and the chain length is j, where the minimum value is divided and where the maximum value is divided

void MinMax(int n, int i, int s, int j, int &minf, int &maxf);
int PolyMax(int n, int &p);
void Show();
int main()
{   
    int p;
    cout<<"Please enter the number of vertices of the polygon: ";
    cin>>N;
    for(int i=1; i<=N; i++)
    {
        cout<<"Please enter polygon vertices"<<i<<"numerical value:";
        cin>>v[i];
        m[i][1][0]=v[i];//Initialization
        m[i][1][1]=v[i];
        cout<<"Please enter a polygon edge"<<i<<"operator:";
        cin>>op[i];
    }
    int ans = PolyMax(N, p);
    cout<<"Polygon Game First Deleted"<<p<<"Bar Edge,The result is:"<<PolyMax(N, p)<<endl;
    Show();
    system("pause");
    return 0;
}

void MinMax(int n, int i, int s, int j, int &minf, int &maxf) //A total of n vertices, starting from vertex i, with j vertices, the break position i s r=(i+s-1)%n+1, minimum minf, maximum maxf
// This function is used to find the minimum and maximum values for polygons where the starting vertex is i, the number of vertices (chain length) is j, and the breaking position is r.
{
    int e[5];
    int a=m[i][s][0], b=m[i][s][1];
    int r=(i+s-1)%n + 1;//Actual vertex number of polygon break position
    int c=m[r][j-s][0], d=m[r][j-s][1];  
    if(op[r] == '+')   //Note that op[r],r i s the break position, so for example, when p(1, 2), 1<=s<=2-1, so the length of the subchain can only be equal to 1, then the break position r = (i+s-1)%n+1=2 i s unique, so op[r] means op[2] corresponds to the symbol between vertex 1 and vertex 2, which must be entered a second time!!!
    {
        minf = a+c;
        maxf = b+d;
    }
    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 r=2; r<5; r++)
        {
            if(minf>e[r]) minf = e[r];
            if(maxf<e[r]) maxf = e[r];
        }
    }
}
int PolyMax(int n, int &p)
{
    int minf, maxf;
    for(int j=2; j<=n; j++)
    {
        for(int i=1; i<=n; i++)
        {
            for(int s=1; s<j; s++)
            {
                MinMax(n,i,s,j,minf,maxf);
                if(m[i][j][0]>minf) m[i][j][0] = minf;  //Updating arrays continuously
                if(m[i][j][1]<maxf) m[i][j][1] = maxf;
            }
        }
    }
    int temp = m[1][n][1];
    p = 1;
    for(int i=2; i<=n; i++)
        if(temp<m[i][n][1])
        {
            temp = m[i][n][1];
            p = i-1;
        }
    if(p==0) p = n;
    return temp;
}
void Show()
{
    cout<<"The resulting three-dimensional array is(The first item in middle bracket represents the minimum value,The latter item represents the maximum value):"<<endl;
    for(int i=1; i<=N; i++)
    {
        for(int j=1; j<=N; j++)
        {
            // cout<<"["<<m[i][j][0]<<","<<m[i][j][1]<<"] ";
            string str = "[";
            str += to_string(m[i][j][0]);
            str += ',';
            str += to_string(m[i][j][1]);
            str += "]";
            cout<<left<<setw(10)<<str;
        }
        cout<<endl;
    }
}

Note the order of input vertex values and symbols!!!

Run result:

Welcome to my personal blog-- George's programming cabin Come on with me!

Tags: Dynamic Programming

Posted on Wed, 01 Dec 2021 14:29:58 -0500 by AudiS2