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 }
View Code

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-09-09
  • 2021-06-03
  • 2021-10-07
  • 2021-07-24
相关资源
相似解决方案