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

POJ 1179 Polygon(环形DP 矩阵连乘)

2014-03-23 10:40 381 查看
题意:给出一个环 环上的每个点有一个值 点和点之间用一条边相连,边上有一个运算符,要求删除一条边,然后对剩下的线两两顶点合并运算.求通过运算能得到的最大值.并求出删除某条边后能经过运算得到这个最大值的这些边.

由于N<=50,所以可以枚举每一个断开点,对断开后形成的线做类似矩阵连乘的DP,这样的复杂度为O(N^4)还是可以接受的.

要注意的是最大值可能有最小值相乘得到(负数),所以也要记录最小值.

设dp1[i][j]为从i到j的最大运算结果,dp2为最小值

那么

dp1[i][j] = max(dp1[i][j], dp1[i][k] + dp1[k + 1][j] | i<=k<j)

dp1[i][j] = max(dp1[i][j], dp1[i][k] * dp1[k + 1][j], dp1[i][k] * dp2[k + 1][j], dp2[i][k] * dp1[k + 1][j], dp2[i][k] * dp2[k + 1][j] | i <= k < j)

dp2的方程和上面差不多,只不过max变成了min

#include <cstdio>
#include <memory.h>
#include <climits>
#include <algorithm>
using namespace std;
const int MAX = 122;

char edg[MAX][2];
int vet[MAX];
int dp1[MAX / 2][MAX / 2], dp2[MAX / 2][MAX / 2];
int final[MAX];
int N;

int main(int argc, char const *argv[]){
int ans_max = INT_MIN, N;
scanf("%d", &N);
for(int i = 0; i < N; ++i){
scanf("%s %d", edg[i], &vet[i]);
edg[i + N][0] = edg[i][0];
vet[i + N] = vet[i];
}

//enumerate every cutting point
for(int k = 0; k < N; ++k){
//base cases
for(int i = 0; i < N; ++i){
dp1[i][i] = vet[k + i];
dp2[i][i] = vet[k + i];
}
//do DP for every line after cutting
for(int i = 1; i < N; ++i){
for(int j = 0; j + i< N; ++j){
int maxv = INT_MIN, minv = INT_MAX;
for(int p = j; p < j + i; ++p){
if(edg[p + k + 1][0] == 't'){
maxv = max(maxv, dp1[j][p] + dp1[p + 1][j + i]);
minv = min(minv, dp2[j][p] + dp2[p + 1][j + i]);
}else{
//minimum times minimum might result in maximum
maxv = max(maxv, dp1[j][p] * dp1[p + 1][j + i]);
maxv = max(maxv, dp1[j][p] * dp2[p + 1][j + i]);
maxv = max(maxv, dp2[j][p] * dp1[p + 1][j + i]);
maxv = max(maxv, dp2[j][p] * dp2[p + 1][j + i]);
//vice versa
minv = min(minv, dp1[j][p] * dp1[p + 1][j + i]);
minv = min(minv, dp1[j][p] * dp2[p + 1][j + i]);
minv = min(minv, dp2[j][p] * dp1[p + 1][j + i]);
minv = min(minv, dp2[j][p] * dp2[p + 1][j + i]);
}
}
dp1[j][j + i] = maxv;
dp2[j][j + i] = minv;
}
}
ans_max = max(ans_max, dp1[0][N - 1]);
final[k] = dp1[0][N - 1];
}
printf("%d\n", ans_max);
for(int i = 0; i < N; ++i){
if(final[i] == ans_max){
printf("%d ", i + 1);
}
}
printf("\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: