zoukankan      html  css  js  c++  java
  • HDU3480-Division-斜率dp

    首先想到的就是sort一下,然后每个集合都在排过序的数组里面取,不重复。

    这样就推出公式dp[i][j] = min(dp[k][j-1] + (s[i]-s[k+1])^2)

    其中dp[i][j]为在第i位完成j个分组的。

    不考虑分组的情况下跟打印文章那题一样。考虑上需要有M个分组,就是两层for循环的dp。

    这里往维护的凸包里添加点的时候,要等这一层全部解决之后再一起添进去。保证处理dp第j层时考虑的都是j-1层的情况。

    还有就是初始化了。

    O(N*M)大概5e7 有点卡,第一次写了个set就TLE了

     1 #include <set>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define LL long long
     6 using namespace std;
     7 
     8 const int maxn = 1e4+10;
     9 const int maxm = 5e3+10;
    10 
    11 struct Point{
    12     LL x,y;
    13     Point(LL _x=0,LL _y=0) :x(_x),y(_y){}
    14     bool operator < (const Point &rhs) const
    15     {
    16         if(x == rhs.x) return y < rhs.y;
    17         else return x <rhs.x;
    18     }
    19     LL operator ^(const Point &rhs) const
    20     {
    21         return x*rhs.y - y*rhs.x;
    22     }
    23     Point operator - (const Point &rhs) const
    24     {
    25         return Point(x-rhs.x,y-rhs.y);
    26     }
    27 };
    28 LL func(Point p,LL k)
    29 {
    30     return p.y - k*p.x;
    31 }
    32 
    33 struct SlopeDP
    34 {
    35     Point ch[maxn];
    36     int head,tail;
    37     void init()
    38     {
    39         tail = 1;head = 0;
    40     }
    41     void push(Point u)
    42     {
    43         while(head >= 1 && ((ch[head]-ch[head-1])^(u-ch[head]) )<=0) head--;
    44         ch[++head] = u;
    45     }
    46     Point pop(int k)
    47     {
    48         while(tail < head && func(ch[tail],k) >= func(ch[tail+1],k) ) tail++;
    49         return ch[tail];
    50     }
    51 };
    52 int T,N,M;
    53 LL s[maxn],dp[maxn][maxm];
    54 //set <Point> st;
    55 Point save[maxn];
    56 
    57 int main()
    58 {
    59     scanf("%d",&T);
    60     int cas = 0;
    61     while(T--)
    62     {
    63         memset(dp,0,sizeof dp);
    64         scanf("%d%d",&N,&M);
    65         for(int i=1;i<=N;i++)
    66         {
    67             scanf("%d",&s[i]);
    68         }
    69         sort(s+1,s+1+N);
    70         SlopeDP H;
    71         H.init();
    72         //st.clear();
    73         int cnt = 0;
    74         for(int i=1;i<=N;i++)
    75         {
    76             dp[i][1] = (s[i] - s[1])*(s[i] - s[1]);
    77             //st.insert(Point(s[i],s[i]*s[i]+dp[i-1][1]));
    78             save[cnt++] = Point(s[i],s[i]*s[i]+dp[i-1][1]);
    79         }
    80 
    81         for(int j=2;j<=M;j++)
    82         {
    83             H.init();
    84             for(int i=0;i<cnt;i++) H.push(save[i]);
    85             cnt = 0;
    86             for(int i=j;i<=N;i++)
    87             {
    88                 Point u = H.pop(2*s[i]);
    89                 dp[i][j] = -2*s[i]*u.x + u.y + s[i]*s[i];
    90                 //printf("i:%d %d x:%d y:%d k:%d
    ",i,dp[i][j],u.x,u.y,-2*s[i]);
    91                 //H.push(Point(s[i+1],s[i+1]*s[i+1]+dp[i][j]));
    92                 save[cnt++] = Point(s[i+1],s[i+1]*s[i+1]+dp[i][j]);
    93             }
    94         }
    95         printf("Case %d: %lld
    ",++cas,dp[N][M]);
    96     }
    97 }
  • 相关阅读:
    心跳机制
    有可能出现的中文乱码
    【学习】logger
    【开发效率】Chrome快捷键
    Unable to open debugger port (127.0.0.1:4184): java.net.SocketException "socket closed"
    将项目发布【2.用idea】
    将项目发布【1.用MobaXterm】
    basePath
    大文件上传如何做断点续传?
    JavaScript如何判断一个元素是否在可视区域中?
  • 原文地址:https://www.cnblogs.com/helica/p/5721858.html
Copyright © 2011-2022 走看看