石子合并(一)
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
3
-
描述
-
有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
-
输入
-
有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开
输出
- 输出总代价的最小值,占单独的一行 样例输入
-
3 1 2 3 7 13 7 8 16 21 4 18
样例输出
-
9 239
-
有多组测试数据,输入到文件结束。
注意单独一堆是不用付出代价的,然后就是裸的区间dp了。区间dp真有意思。。。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <string>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (200+10)
#define MAXM (500000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
using namespace std;
int a[MAXN], dp[MAXN][MAXN];
int sum[MAXN];
int DFS(int i, int j)
{
if(dp[i][j] != -1) return dp[i][j];
if(i >= j) return 0;
dp[i][j] = INF;
for(int k = i; k <= j; k++)
dp[i][j] = min(dp[i][j], DFS(i, k) + DFS(k+1, j) + sum[j] - sum[i-1]);
return dp[i][j];
}
int main()
{
int n;
while(Ri(n) != EOF)
{
sum[0] = 0;
for(int i = 1; i <= n; i++)
Ri(a[i]), sum[i] = sum[i-1] + a[i];
CLR(dp, -1);
Pi(DFS(1, n));
}
return 0;
}