POJ 1179 Polygon
http://poj.org/problem?id=1179
1》给出的样例,取得的最优值为去掉2边后结果为:4*2*5-7=33。
2》对于加法两个最优的相加肯定是最优的,但是对于乘法:
求最大值: |
正数X正数 |
两个都是最大的 |
结果最大 |
正数X负数 |
正数最小,负数最大 |
结果最大 |
|
负数X负数 |
两个都是最小值 |
结果最大 |
|
求最小值: |
正数X正数 |
两个都是最小值 |
结果最小 |
正数X负数 |
正数最大,负数最小 |
结果最小 |
|
负数X负数 |
两个都最大 |
结果最小 |
要保存子问题的最大值和最小值,还具有点最优子结构,可以用动态规划求解。
fmin(i, L)表示以i为首,顺时针长度为L的链的计算结果最小值。
fmax(i, L)表示以i为首,顺时针长度为L的链的计算结果最大值。
然后枚举t(0<=t<L),求出区间的最大值or最小值
fmin={ fmin(i, t)+fmin((i+t)%n+1, L-t-1 } ,当opr((i+t-1)%n==’+’
min{fmin(i, t) +fmin(i+t)%n+1, L-t-1 )
fmin(i, t)+fmax(i+t)%n+1, L-t-1)
fmax(i, t)+fmax(i+t)%n+1, L-t-1)
fmax(i, t)+fmin(i+t)%n+1, L-t-1)
} ,当opr((i+t-1)%n==‘*’
fmax={fmax(i, t)+fmax((i+t)%n+1, L-t-1) },当opr((i+t-1)%n==’+’
Max{ fmin(i, t) +fmin(i+t)%n+1, L-t-1 )
fmin(i, t)+fmax(i+t)%n+1, L-t-1)
fmax(i, t)+fmax(i+t)%n+1, L-t-1)
fmax(i, t)+fmin(i+t)%n+1, L-t-1)
} ,当opr((i+t-1)%n==‘*’
3》初始化fmin(i, 0) = num[i], fmax(i, 0)=num[i];
代码如下:
/* POJ 1179 多边形计算 */ #include<iostream> #include<string.h> using namespace std; #define N 105 int main() { int i, L, t, minnum, maxnum, mm, n; int fmax[N][N], fmin[N][N], num[N], pos[N]; char opr[N]; while(cin>>n) { for(i=0; i<n; i++) cin>>opr[i]>>num[i]; for(i=0; i<n; i++) fmax[i][0]=num[i], fmin[i][0]=num[i]; for(L=1; L<n; L++) //长度 for(i=0; i<n; i++) { fmax[i][L]=-65535; fmin[i][L]=65535; for(t=0; t<L; t++) { if(opr[(i+t+1)%n]=='t') { minnum=fmin[i][t]+fmin[(i+t+1)%n][L-1-t]; maxnum=fmax[i][t]+fmax[(i+t+1)%n][L-1-t]; if(fmin[i][L]>minnum) fmin[i][L]=minnum; if(fmax[i][L]<maxnum) fmax[i][L]=maxnum; } if(opr[(i+t+1)%n]=='x') { mm=fmin[i][t]*fmin[(i+t+1)%n][L-t-1]; if(fmin[i][L]>mm) fmin[i][L]=mm; if(fmax[i][L]<mm) fmax[i][L]=mm; mm=fmin[i][t]*fmax[(i+t+1)%n][L-t-1]; if(fmin[i][L]>mm) fmin[i][L]=mm; if(fmax[i][L]<mm) fmax[i][L]=mm; mm=fmax[i][t]*fmax[(i+t+1)%n][L-t-1]; if(fmin[i][L]>mm) fmin[i][L]=mm; if(fmax[i][L]<mm) fmax[i][L]=mm; mm=fmax[i][t]*fmin[(i+t+1)%n][L-t-1]; if(fmin[i][L]>mm) fmin[i][L]=mm; if(fmax[i][L]<mm) fmax[i][L]=mm; } } } mm=fmax[0][n-1]; for(i=1; i<n; i++) if(mm<fmax[i][n-1]) mm=fmax[i][n-1]; cout<<mm<<endl; int flag=0; for(i=0; i<n; i++) if(mm==fmax[i][n-1]) pos[flag++]=i%n+1; for(i=0; i<flag; i++) { cout<<pos[i]; if(i<flag-1) cout<<" "; } cout<<endl; } return 0; }