本题一次水过,由此纪念一下。(实际上,我这个年纪做这种题实在很丢人)。
题目链接。大意:给一个多边形,每个顶点有一个值,每个边编号从1到N,边的属性是加或者乘。首先先拆掉一条边,剩下的如下做:选定一条边以及这条边的两个端点(两个数)用新顶点替换(新顶点即:按照这条边的属性(加或乘)算出这两个数的乘积或者和)。到最后剩一个点,也就是一个值。求这些值的最大值输出,并输出此时最先拆掉的是哪条边。
用2个一维数组存放这个多边形,其一存放点,其二存放边(加或者乘)。将这2个数组当作循环队列一样的使用即可穷举去掉的边。需要另外2个数组记录最大值和最小值(因为两个负数相乘为正,所以要记录最小值)。
设maxDp[i][j] (minDp[i][j])为从i到j的多边形的最终值的最大值(最小值),再从1到N枚举多边形长度(j-i),依次算出长度为1到N的子多边形的最终值。由此自底向上就算出此多边形的最终值的最大值。我的代码如下:
1: #include <iostream>
2: #include <algorithm>
3:
4: using namespace std;
5: const int VERTEX_SIZE = 50;
6: const long MAX_INT = (1<<15);
7: const long MIN_INT = -(1<<15);
8:
9: int vertex[VERTEX_SIZE];
10: char label[VERTEX_SIZE];
11: long maxDp[VERTEX_SIZE][VERTEX_SIZE];
12: long minDp[VERTEX_SIZE][VERTEX_SIZE];
13:
14: void init(const int size, const int front)
15: {
16: for (int i=0; i<VERTEX_SIZE; i++)
17: {
18: for (int j=0; j<VERTEX_SIZE; j++)
19: {
20: if (j==i)
21: minDp[i][j] = maxDp[i][j] = vertex[i];
22: else
23: {
24: maxDp[i][j] = MIN_INT;
25: minDp[i][j] = MAX_INT;
26: }
27: }
28: }
29: }
30:
31: int getRes(const int size, const int front)
32: {
33: int end=(front+size)%size;
34: for (int len=1; len<size; len++)
35: {
36: bool flag=true;
37: for (int i=front; flag || (i+len)%size!=end; i=(i+1)%size)
38: {
39: flag = false;
40: int j=(i+len)%size;
41: for (int k=i; k!=j; k=(k+1)%size)
42: {
43: if (label[(k+1)%size]=='x')
44: {
45: maxDp[i][j] = max(maxDp[i][j], maxDp[i][k]*maxDp[(k+1)%size][j]);
46: maxDp[i][j] = max(maxDp[i][j], minDp[i][k]*minDp[(k+1)%size][j]);
47:
48: minDp[i][j] = min(minDp[i][j], maxDp[i][k]*maxDp[(k+1)%size][j]);
49: minDp[i][j] = min(minDp[i][j], maxDp[i][k]*minDp[(k+1)%size][j]);
50: minDp[i][j] = min(minDp[i][j], minDp[i][k]*maxDp[(k+1)%size][j]);
51: minDp[i][j] = min(minDp[i][j], minDp[i][k]*minDp[(k+1)%size][j]);
52: }
53: else if (label[(k+1)%size]=='t')
54: {
55: maxDp[i][j] = max(maxDp[i][j], maxDp[i][k]+maxDp[(k+1)%size][j]);
56: minDp[i][j] = min(minDp[i][j], minDp[i][k]+minDp[(k+1)%size][j]);
57: }
58: }
59: }
60: }
61:
62: return maxDp[front][(front+size-1)%size];
63: }
64:
65: int main()
66: {
67: int size=0;
68: cin >> size;
69: for (int i=0; i<size; i++)
70: cin >> label[i] >> vertex[i];
71: int recordLabel[VERTEX_SIZE]={0};
72: int maxNum = MIN_INT;
73: for (int i=0; i<size; i++)
74: {
75: init(size, i);
76: recordLabel[i] = getRes(size, i);
77: maxNum = max(maxNum, recordLabel[i]);
78: }
79: cout << maxNum << endl;
80: bool first = true;
81: for (int i=0; i<size; i++)
82: {
83: if (maxNum==recordLabel[i] && first)
84: {
85: cout << (i+1);
86: first = false;
87: continue;
88: }
89: if (maxNum==recordLabel[i] && (!first))
90: {
91: cout << ' ' << (i+1);
92: continue;
93: }
94: }
95: cout << endl;
96:
97: return 0;
98: }