注意一点:
在加法的时候最大值肯定是两个最大值相加,最小值肯定是两个最小值相加
在乘法的时候 最大值可能是两个最大值相乘 也可能是两个最小值相乘,最小值可能是两个最小值相乘,也可能是一个最大值和一个最小值
然后我用的是记忆化搜索:dp_min[i][j]表示区间i到j的最小值, dp_max[i][j]表示区间i到j的最大值
AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
using namespace std;
#define MAX 0x3f3f3f3f
char edge[55];
int num[55], N;
int ans[55];
int dp_min[55][55], dp_max[55][55];
char temp_edge[55];
int temp_num[55];
int max_ans;
int DFS_max( int start, int ends );
int calc( int a, int b ){
if( temp_edge[b] == 't' ){
return temp_num[a] + temp_num[b];
}else{
return temp_num[a] * temp_num[b];
}
}
int DFS_min( int start, int ends ){//区间start到ends所能获得的最小值
if( start + 1 == ends ){
return calc( start, ends );
}
if( start == ends ){
return temp_num[start];
}
if( dp_min[start][ends] != MAX ){
return dp_min[start][ends];
}
int ans = MAX;
for( int i = start; i < ends; i++ ){
int temp;
if( temp_edge[i+1] == 't' ){
temp = DFS_min( start, i ) + DFS_min( i + 1, ends );
}else{
temp = DFS_min( start, i ) * DFS_min( i + 1, ends );
temp = min( temp, ( DFS_max( start, i ) * DFS_min( i + 1, ends ) ) );
temp = min( temp, DFS_min( start, i ) * DFS_max( i + 1, ends ) );
}
ans = min( ans, temp );
}
return dp_min[start][ends] = ans;
}
int DFS_max( int start, int ends ){//区间start到ends所能获得的最大值
if( start + 1 == ends ){
return calc( start, ends );
}
if( start == ends ){
return temp_num[start];
}
if( dp_max[start][ends] != MAX ){
return dp_max[start][ends];
}
int ans = -MAX;
for( int i = start; i < ends; i++ ){
int temp;
if( temp_edge[i+1] == 't' ){
temp = DFS_max( start, i ) + DFS_max( i + 1, ends );
}else{
temp = DFS_max( start, i ) * DFS_max( i + 1, ends );
temp = max( temp, DFS_min( start, i ) * DFS_min( i + 1, ends ) );
}
ans = max( ans, temp );
}
return dp_max[start][ends] = ans;
}
int main(){
while( scanf( "%d", &N ) != EOF ){
//读数据
getchar();
for( int i = 1; i < N; i++ ){
scanf( "%c %d ", &edge[i], &num[i] );
}
scanf( "%c %d", &edge[N], &num[N] );
//对每个边进行遍历
max_ans = -MAX;
for( int i = 1; i <= N; i++ ){
//重新排序放在temp数组中
temp_num[1] = num[i];
int k = 2;
for( int j = ( i == N )? 1 : i + 1; j != i; j = ( j == N )? 1 : j + 1 ){
temp_num[k] = num[j];
temp_edge[k++] = edge[j];
}
memset( dp_max, 0x3f, sizeof( dp_max ) );
memset( dp_min, 0x3f, sizeof( dp_min ) );
ans[i] = DFS_max( 1, N );
max_ans = max( max_ans, ans[i] );
}
cout << max_ans << endl;
int flag = 1;
for( int i = 1; i <= N; i++ ){
if( max_ans == ans[i] ){
if( !flag ){
cout << " ";
}
cout << i;
flag = 0;
}
}
cout << endl;
}
return 0;
}