您的位置:首页 > 编程语言 > Go语言

poj-1179 Polygon **

2012-03-25 21:00 375 查看
/*
* 枚举第一次断开的边,然后DP,
*
* DP还是很简单的, 类似矩阵连乘
* 需要注意的是:由于负负得正,所以你不能只算最大值.
* 也就是说要计算多边形上连续的一段所能达到的最小值和最大值.
*
* 难的是断开第k条边后如何给剩下的边重新编号
*
* 这里建立了一个映射,如断开第k条边,
* 则原来的第k+1条边编号为0,原来的第k-1条边编号为n-2.
*
* getNum(i, k)函数用于计算断开第k条边后新编号为i的边的原编号
*
*
*
*/
#include <cstdio>
using namespace std;

const int maxn = 50 + 4;
const int inf = 10000000;
int n, vertex[maxn];
char edge[maxn];
int dpmin[maxn][maxn], dpmax[maxn][maxn], initdp[maxn];

inline int cal(int edgeNum, int a, int b){
if(edge[edgeNum] == 't')
return a + b;
else
return a * b;
}
inline int getNum(int i, int k){
if(i > n-k-2)
return i-(n-k-1);
else
return i+k+1;
}

//断开第k条边
//
void init(int k){
for(int i=0; i<n; i++)
for(int j=0; j<n; j++){
dpmin[i][j] = inf;
dpmax[i][j] = -inf;
}
int j;
for(int i=0; i<n; i++){
j = getNum(i, k);
//初始化
dpmax[i][i] = dpmin[i][i] = initdp[j];
//为了后边DP时计算方便,把顶点的信息记录在dp数组里
dpmax[(i+1)%n][i] = dpmin[(i+1)%n][i] = vertex[j];
}

}

inline int min(int a, int b, int c, int d, int e){
int ans = a;
if(ans > b) ans = b;
if(ans > c) ans = c;
if(ans > d) ans = d;
if(ans > e) ans = e;
return ans;
}
inline int max(int a, int b, int c, int d, int e){
int ans = a;
if(ans < b) ans = b;
if(ans < c) ans = c;
if(ans < d) ans = d;
if(ans < e) ans = e;
return ans;
}

int main(){
scanf("%d\n", &n);

char tmp;
int ii;
for(int i=0; i<n; i++){
scanf("%c %d", &edge[i], &vertex[i]);
if(i<n-1) scanf("%c", &tmp);
}

for(int i=0; i<n; i++){
ii = (i-1+n) % n;
initdp[i] = cal(i, vertex[ii], vertex[i]);
}

int jj, ans=-inf, rec[maxn], top = 0;
for(int k=0; k<n; k++){
init(k);
for(int l=1; l<n-1; l++){
for(int i=0; i<n-1-l; i++){
for(int j=i; j<=i+l; j++){
jj = getNum(j, k);
ii = (j-1+n)%n;
dpmin[i][i+l]=min(dpmin[i][i+l],
cal(jj, dpmin[i][ii], dpmin[j+1][i+l]),
cal(jj, dpmax[i][ii], dpmin[j+1][i+l]),
cal(jj, dpmin[i][ii], dpmax[j+1][i+l]),
cal(jj, dpmax[i][ii], dpmax[j+1][i+l]));
dpmax[i][i+l]=max(dpmax[i][i+l],
cal(jj, dpmin[i][ii], dpmin[j+1][i+l]),
cal(jj, dpmax[i][ii], dpmin[j+1][i+l]),
cal(jj, dpmin[i][ii], dpmax[j+1][i+l]),
cal(jj, dpmax[i][ii], dpmax[j+1][i+l]));
}
}
}
//记录答案
if(ans < dpmax[0][n-2]){
ans = dpmax[0][n-2];
top = 0;
rec[top++] = k;
}
else if(ans == dpmax[0][n-2])
rec[top++] = k;

}

//answer
printf("%d\n", ans);
for(int i=0; i<top-1; i++)
printf("%d ", rec[i]+1);
printf("%d\n", rec[top-1]+1);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: