Title:
This topic gives a polygon with N vertices, each vertex is marked with a number to represent the value of the point, each edge is marked with "+" to represent addition or "*" to represent multiplication, and these edges are numbered from 1 to N. Figure 1 shows a polygon with N=4.
Rules of the game:
1. Remove one edge first.
2. Select an edge E and two vertices V1 and V2 connected to edge E, and replace them with a new vertex. The value of the new vertex is the result of the operation of the operator marked on edge E on the values of V1 and V2.
3. Repeat step 2 until there is only one vertex left, and the value on this vertex is the game score.
Input format:
The input data has two lines. The first line is the number N (3 < = N < = 50), and the second line gives the operator on the edge (the letter t represents addition and the letter x represents multiplication) and the value of the vertex alternately, separated by spaces.
Output format:
The first line outputs the maximum score.
The second line outputs which edge the game removes in the first step may make the result score the highest. If there are multiple possibilities, all are output, and there is a space after each number.
Input example:
This example is the same as the example shown in the figure. The first line indicates that N=4, the second line indicates that the symbol on the first edge is addition, the vertex value between the first edge and the second edge is - 7, the symbol on the second edge is addition, and the vertex value between the second edge and the third edge is 4, and so on.
4
t -7 t 4 x 2 x 5
No blank lines at the end
Output example:
33
1 2
No blank lines at the end
Problem solving ideas:
This problem belongs to dynamic programming, and the core idea is the idea of matrix multiplication. It is required to find out how to break the ring into a chain and how to combine the operation after breaking to obtain the maximum value. It is very similar to how a matrix is bracketed.
1. Preparatory work: set a sum array to store the maximum value of the chain operation after the i-th edge is broken.
num1 and op1 are used to store the most original numbers and operator information. Num2 and op2 are operands and operators that change the order for breaking an edge.
2. Perform the following operations on each chain:
Find the best combination mode. The state transition equation is as follows. Take the maximum value m[0][n-1] of the whole chain as the value of this chain (after breaking this edge), that is, sum[edge]=m[0][n-1];
3. Select the most value in sum array.
state transition
m[i][j]=max ( m[i][j] , am(m[i][k], m[k+1][j] , op2[k]) ); //The am function indicates that m[i][k] and m[k+1][j] are op2[k] operated. //That is, take the breakpoint k between i-j, and compare the previous two parts with the original m[i][j] after + or * operation, and take the larger value.
Operation of breaking each edge:
code:
#include<bits/stdc++.h> using namespace std; int am(int x,int y,char op)//add or multipuly { if(op=='t')return x+y; else if(op=='x')return x*y; } int main() { int n; int sum[100];//Record the maximum combination value of deleted edges int num1[100];//Record initial data int num2[100];//Data for a removed edge char op1[100];//Record initial data char op2[100];//Data for a removed edge int m[100][100];//Record status cin>>n; cin.get(); // getline(cin,str); // for(int i=0;i<str.size();i++) // { // if(str[i]=='t'||str[i]=='x')op1[temp1++]=str[i]; // if(str[i]>='0'&&str[i]<='9') // { // int number=0,j; // for(j=i;;j++) // { // if(str[j]<'0'||str[j]>'9')break; // number=number*10+str[j]-'0'; // } // if(str[i-1]=='-')number*=-1; // num1[temp2++]=number; // i=j; // } // } for(int i=0;i<n;i++) cin>>op1[i]>>num1[i]; //The number of data groups is determined. You can directly enter operators and operands in groups. The above is the input method of unknown groups for(int edge=0;edge<n;edge++)//Discuss side i { char ch=op1[edge]; op1[edge]='/'; //Erase the operator on this side temporarily, but remember to recover when you run out. int t=0; for(int i=0;i<n;i++)//This loop is to find the order of operands and operators after a break on one side { num2[i]=num1[(edge+i)%n]; if(i==n-1)continue; if(op1[(edge+i)%n]=='/')t=1;//In order to discard the erased operator, just move the following symbols one op2[i]=op1[(edge+i+t)%n]; } memset(m,0,sizeof(m));//The m of each edge operation is different, so it needs to be initialized every time before use. Here, the initial value is 0 for(int i=0;i<n;i++)m[i][i]=num2[i]; for(int r=1;r<n;r++)//The standard matrix combines the idea of three cycles. { for(int i=0;i<n-r;i++) { int j=i+r; for(int k=i;k<j;k++) { m[i][j]=max(m[i][j],am(m[i][k],m[k+1][j],op2[k])); } } } sum[edge]=m[0][n-1]; op1[edge]=ch;//Restore edge } int max=0; for(int i=0;i<n;i++) { if(sum[i]>sum[max])max=i; } cout<<sum[max]<<endl; for(int i=0;i<n;i++) { if(sum[i]==sum[max])cout<<i+1<<" "; } return 0; }