http://poj.org/problem?id=1738
题目大意:有n堆石子排在一行,每堆石子给定一个重量。要把n堆石子合并成一堆,每次合并智能将相邻的两堆石子合并成一堆,代价为这两堆石子的重量和,求最小的总代价。
参考资料:
http://wenku.baidu.com/view/84c326fb700abb68a982fbcc.html
http://fanhq666.blog.163.com/blog/static/81943426201062865551410/
http://hi.baidu.com/nyroro/item/4ad998fc1234cad242c36a86
下面是GarsiaWachs算法的代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <set> #include <map> #include <cmath> #include <queue> using namespace std; template <class T> void checkmin(T &t,T x) {if(x < t) t = x;} template <class T> void checkmax(T &t,T x) {if(x > t) t = x;} template <class T> void _checkmin(T &t,T x) {if(t==-1) t = x; if(x < t) t = x;} template <class T> void _checkmax(T &t,T x) {if(t==-1) t = x; if(x > t) t = x;} typedef pair <int,int> PII; typedef pair <double,double> PDD; typedef long long ll; #define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end ; it ++) const int N = 50050; int n , t , stone[N] , ans; void combine(int k) { int tmp = stone[k] + stone[k-1]; ans += tmp; for(int i=k;i<t-1;i++) stone[i] = stone[i+1]; t --; int j; for(j=k-1;j>0 && stone[j-1]<tmp;j--) stone[j] = stone[j-1]; stone[j] = tmp; while(j >= 2 && stone[j] >= stone[j-2]) { int d = t - j; combine(j-1); j = t-d; } } int main() { while(~scanf("%d",&n) && n) { for(int i=0;i<n;i++) scanf("%d",&stone[i]); t = 1 , ans = 0; for(int i=1;i<n;i++) { stone[t++] = stone[i]; while(t >= 3 && stone[t-3] <= stone[t-1]) { combine(t-2); } } while(t > 1) combine(t-1); printf("%d\n" , ans); } return 0; }