您的位置:首页 > 其它

PID490 / [NOI1995]石子合并

2013-11-24 19:38 274 查看
题目描述
在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。

试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.

输入格式
数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.

输出格式
输出共2行,第1行为最小得分,第2行为最大得分.

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int INF = 1<<30;
const int N = 210;
int n;
int num
, sum
;
int dpMax

, dpMin

;

void init(){
memset(sum , 0 , sizeof(sum));
for(int i = 1 ; i <= 2*n ; i++){
dpMax[i][i] = dpMin[i][i] = 0;
sum[i] = sum[i-1]+num[i];;
}
}

void solve(){
for(int k = 1 ; k < n ; k++){//枚举区间的长度
for(int i = 1 ; i <= 2*n-k ; i++){//区间的左端点
int j = i+k;//区间的右端点
dpMax[i][j] = -INF;
dpMin[i][j] = INF;
//枚举区间的剖分点
for(int p = i ; p < j ; p++){
int score = sum[j]-sum[i-1];
dpMax[i][j] = max(dpMax[i][j],dpMax[i][p]+dpMax[p+1][j]+score);
dpMin[i][j] = min(dpMin[i][j],dpMin[i][p]+dpMin[p+1][j]+score);
}
}
}
int minSco = INF;
int maxSco = -INF;
for(int i = 1 ; i <= n ; i++){
minSco = min(minSco , dpMin[i][i+n-1]); //注意区间长度为n那么右端点是i+n-1
maxSco = max(maxSco , dpMax[i][i+n-1]);
}
printf("%d\n%d\n" , minSco , maxSco);
}

int main(){
while(scanf("%d" , &n) != EOF){
for(int i = 1 ; i <= n ; i++){
scanf("%d" , &num[i]);
num[i+n] = num[i];
}
init();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: