uva 12524
题意:沿河有n个点,每个点有w的东西,有一艘船从起点出发,沿途可以装运东西和卸载东西,船的容量无限,每次把wi的东西从x运到y的花费为(y-x)*wi;
问把n个点的东西合并成k个的最小花费;
分析:设dp[j][i]表示把前i个点的东西合并成j个点的最小花费,那么dp[j][i] = min( dp[j-1][k] + w[k+1]*(x[i] - x[k+1]) + w[k+2]*(x[i] - x[k+2]) + ... + w[i] * (x[i] - x[i]));
设sw[i] = w[1] + w[2] + ...+w[i];
swx[i] = w[1]*x[1] + w[2]*x[2] + ... + w[i]*x[i];
那么 dp[j][i] = min( dp[j-1][k] + x[i] * (sw[i] - sw[k]) - (swx[i] - swx[k]) , 0<k<i );
显然dp[j][i] = -x[i] * sw[k] + swx[k] + dp[j-1][k] + x[i] * sw[i] - swx[i];
斜率为 x[i];
x = sw[k]; y = swx[k] + dp[j-1][k];然后套模板;
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<vector> 6 #include<cstdlib> 7 #include<cstring> 8 #include<set> 9 #include<map> 10 #include<queue> 11 #define lson l,m,rt<<1 12 #define rson m+1,r,rt<<1|1 13 #define pbk push_back 14 #define mk make_pair 15 using namespace std; 16 typedef long long LL; 17 const int N = 1000+10; 18 const double eps = 1e-8; 19 inline int dcmp(double x) { 20 return x < -eps ? -1 : x > eps; 21 } 22 LL x[N],sw[N],swx[N],w[N]; 23 int n,k; 24 LL dp[N][N]; 25 struct Point{ 26 LL x,y; 27 Point (LL x = 0, LL y = 0):x(x),y(y){} 28 Point operator - (const Point &p)const{ 29 return Point(x - p.x, y - p.y); 30 } 31 LL operator * (const Point &p)const{ 32 return x * p.y - y * p.x; 33 } 34 }; 35 struct dequeue{ 36 int head,tail; 37 Point q[N]; 38 void init(){ 39 head = 1; tail = 0; 40 } 41 void push(const Point &u){ 42 while (head < tail && (q[tail] - q[tail - 1]) * (u - q[tail - 1]) <= 0 ) tail--; 43 q[++tail] = u; 44 } 45 Point pop(const LL &k) { 46 while (head < tail && k*q[head].x + q[head].y >= k*q[head+1].x + q[head+1].y) head++; 47 return q[head]; 48 } 49 }H; 50 void solve(){ 51 sw[0] = swx[0] = 0; 52 for (int i = 1; i <= n; i++) { 53 sw[i] = sw[i-1] + w[i]; 54 swx[i] = swx[i-1] + w[i]*x[i]; 55 } 56 memset(dp,0,sizeof(dp)); 57 for (int i = 1; i <= n; i++) { 58 dp[1][i] = x[i]*sw[i] - swx[i]; 59 } 60 for (int j = 2; j <= k; j++){ 61 H.init(); 62 63 H.push(Point(sw[j-1],swx[j-1] + dp[j-1][j-1])); 64 for (int i = j; i <= n; i++) { 65 Point p = H.pop(-x[i]); 66 dp[j][i] = x[i]*sw[i] - swx[i] - x[i] * p.x + p.y; 67 H.push(Point(sw[i],swx[i] + dp[j-1][i])); 68 } 69 } 70 printf("%lld\n",dp[k][n]); 71 72 } 73 int main(){ 74 while (~scanf("%d%d",&n,&k)) { 75 for (int i = 1; i <= n; i++) { 76 scanf("%lld%lld",&x[i],&w[i]); 77 } 78 solve(); 79 } 80 return 0 ; 81 }