poj-1179 Polygon **

  1 /*
2 * 枚举第一次断开的边,然后DP,
3 *
4 * DP还是很简单的, 类似矩阵连乘
5 * 需要注意的是:由于负负得正,所以你不能只算最大值.
6 * 也就是说要计算多边形上连续的一段所能达到的最小值和最大值.
7 *
8 * 难的是断开第k条边后如何给剩下的边重新编号
9 *
10 * 这里建立了一个映射,如断开第k条边,
11 * 则原来的第k+1条边编号为0,原来的第k-1条边编号为n-2.
12 *
13 * getNum(i, k)函数用于计算断开第k条边后新编号为i的边的原编号
14 *
15 *
16 *
17 */
18 #include <cstdio>
19 using namespace std;
20
21 const int maxn = 50 + 4;
22 const int inf = 10000000;
23 int n, vertex[maxn];
24 char edge[maxn];
25 int dpmin[maxn][maxn], dpmax[maxn][maxn], initdp[maxn];
26
27 inline int cal(int edgeNum, int a, int b){
28 if(edge[edgeNum] == 't')
29 return a + b;
30 else
31 return a * b;
32 }
33 inline int getNum(int i, int k){
34 if(i > n-k-2)
35 return i-(n-k-1);
36 else
37 return i+k+1;
38 }
39
40 //断开第k条边
41 //
42 void init(int k){
43 for(int i=0; i<n; i++)
44 for(int j=0; j<n; j++){
45 dpmin[i][j] = inf;
46 dpmax[i][j] = -inf;
47 }
48 int j;
49 for(int i=0; i<n; i++){
50 j = getNum(i, k);
51 //初始化
52 dpmax[i][i] = dpmin[i][i] = initdp[j];
53 //为了后边DP时计算方便,把顶点的信息记录在dp数组里
54 dpmax[(i+1)%n][i] = dpmin[(i+1)%n][i] = vertex[j];
55 }
56
57 }
58
59 inline int min(int a, int b, int c, int d, int e){
60 int ans = a;
61 if(ans > b) ans = b;
62 if(ans > c) ans = c;
63 if(ans > d) ans = d;
64 if(ans > e) ans = e;
65 return ans;
66 }
67 inline int max(int a, int b, int c, int d, int e){
68 int ans = a;
69 if(ans < b) ans = b;
70 if(ans < c) ans = c;
71 if(ans < d) ans = d;
72 if(ans < e) ans = e;
73 return ans;
74 }
75
76
77 int main(){
78 scanf("%d\n", &n);
79
80 char tmp;
81 int ii;
82 for(int i=0; i<n; i++){
83 scanf("%c %d", &edge[i], &vertex[i]);
84 if(i<n-1) scanf("%c", &tmp);
85 }
86
87 for(int i=0; i<n; i++){
88 ii = (i-1+n) % n;
89 initdp[i] = cal(i, vertex[ii], vertex[i]);
90 }
91
92 int jj, ans=-inf, rec[maxn], top = 0;
93 for(int k=0; k<n; k++){
94 init(k);
95 for(int l=1; l<n-1; l++){
96 for(int i=0; i<n-1-l; i++){
97 for(int j=i; j<=i+l; j++){
98 jj = getNum(j, k);
99 ii = (j-1+n)%n;
100 dpmin[i][i+l]=min(dpmin[i][i+l],
101 cal(jj, dpmin[i][ii], dpmin[j+1][i+l]),
102 cal(jj, dpmax[i][ii], dpmin[j+1][i+l]),
103 cal(jj, dpmin[i][ii], dpmax[j+1][i+l]),
104 cal(jj, dpmax[i][ii], dpmax[j+1][i+l]));
105 dpmax[i][i+l]=max(dpmax[i][i+l],
106 cal(jj, dpmin[i][ii], dpmin[j+1][i+l]),
107 cal(jj, dpmax[i][ii], dpmin[j+1][i+l]),
108 cal(jj, dpmin[i][ii], dpmax[j+1][i+l]),
109 cal(jj, dpmax[i][ii], dpmax[j+1][i+l]));
110 }
111 }
112 }
113 //记录答案
114 if(ans < dpmax[0][n-2]){
115 ans = dpmax[0][n-2];
116 top = 0;
117 rec[top++] = k;
118 }
119 else if(ans == dpmax[0][n-2])
120 rec[top++] = k;
121
122 }
123
124 //answer
125 printf("%d\n", ans);
126 for(int i=0; i<top-1; i++)
127 printf("%d ", rec[i]+1);
128 printf("%d\n", rec[top-1]+1);
129
130
131 return 0;
132 }

posted on 2012-03-25 21:00  龙豆  阅读(389)  评论(0编辑  收藏  举报

导航