• HDU 3480 Division(斜率DP裸题)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3480

    题目大意:将n个数字分成m段,每段价值为(该段最大值-该段最小值)^2,求最小的总价值。

    解题思路:很单纯的斜率优化DP,得出状态转移方程:dp[i][j]=min{dp[k][j-1]+(a[i]-a[k+1])^2}(j-1<=k<i),然后斜率优化降到O(n^2)就好了。

         注意:数据类型建议用int,不要用long long,后者乘法计算时间是前者的四倍,否则C++可能会超时。

    代码:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef long long LL;
     7 const int N=1e4+5;
     8 
     9 int head,tail;
    10 int dp[N][5005],a[N],q[N];
    11 
    12 int getUP(int m,int k,int j){
    13     return dp[k][j-1]+a[k+1]*a[k+1]-dp[m][j-1]-a[m+1]*a[m+1];
    14 }
    15 
    16 int getDOWN(int m,int k){
    17     return 2*(a[k+1]-a[m+1]);
    18 }
    19 
    20 //dp[i][j]=min{dp[k][j-1]+(a[i]-a[k+1])^2}
    21 int getDP(int i,int j,int k){
    22     return dp[k][j-1]+(a[i]-a[k+1])*(a[i]-a[k+1]);
    23 }
    24 
    25 int main(){
    26     int t,cas=0;
    27     scanf("%d",&t);
    28     int cnt=0;
    29     while(t--){
    30         int n,m;
    31         scanf("%d%d",&n,&m);
    32         for(int i=1;i<=n;i++){
    33             scanf("%d",&a[i]);
    34         }
    35         sort(a+1,a+1+n);
    36         for(int i=1;i<=n;i++){
    37             dp[i][1]=(a[i]-a[1])*(a[i]-a[1]);
    38         }
    39         
    40         for(int j=2;j<=m;j++){
    41             head=tail=0;
    42             q[tail++]=j-1;
    43             for(int i=j;i<=n;i++){
    44                 cnt++;
    45                 while(head+1<tail&&getUP(q[head],q[head+1],j)<=a[i]*getDOWN(q[head],q[head+1])){
    46                     head++;
    47                 }
    48                 dp[i][j]=getDP(i,j,q[head]);
    49                 while(head+1<tail&&getUP(q[tail-1],i,j)*getDOWN(q[tail-2],q[tail-1])<=getUP(q[tail-2],q[tail-1],j)*getDOWN(q[tail-1],i)){
    50                     tail--;
    51                 }
    52                 q[tail++]=i;
    53             }
    54         }
    55         printf("Case %d: %d
    ",++cas,dp[n][m]);
    56     }
    57     return 0;
    58 }
  • 相关阅读:
    vim
    echo
    kill/xkill/killall/pkill/pidof
    ssh
    使用GSON
    使用GSON
    解析JSON
    解析JSON
    Pull解析方式
    Pull解析方式
  • 原文地址:https://www.cnblogs.com/fu3638/p/7850650.html
Copyright © 2020-2023  润新知