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\n",++cas,dp[n][m]);
56     }
57     return 0;
58 }
时间: 2024-10-03 14:57:39

HDU 3480 Division(斜率DP裸题)的相关文章

HDU 3480 - Division - [斜率DP]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3480 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 999999/400000 K (Java/Others) Little D is really interested in the theorem of sets recently. There's a problem that confused him a long time.   

hdu 3480 Division (斜率优化)

Division Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 999999/400000 K (Java/Others) Total Submission(s): 2676    Accepted Submission(s): 1056 Problem Description Little D is really interested in the theorem of sets recently. There's a pro

HDU 4280 Island Transport 网络流裸题

非递归版好像被卡掉了,其他2个板子都能过. #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<vector> using namespace std; #define ll int const int MAXN = 100100;//点数的最大值 const int MAXM = 400010;//边数的最大值 const in

hdu 2085 数塔 -- dp模板题

数塔 Problem Description 在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的: 有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少? 已经告诉你了,这是个DP的题目,你能AC吗? Input 输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数,且所有的整数均在区间[0,99]内. Outp

hdu 5001 walk 概率dp入门题

Description I used to think I could be anything, but now I know that I couldn't do anything. So I started traveling. The nation looks like a connected bidirectional graph, and I am randomly walking on it. It means when I am at node i, I will travel t

HDU 3480 Division(斜率优化+二维DP)

Division Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 999999/400000 K (Java/Others) Total Submission(s): 3984    Accepted Submission(s): 1527 Problem Description Little D is really interested in the theorem of sets recently. There’s a pro

【BZOJ1911】【Apio2010】特别行动队,斜率优化DP裸题(斜率有单调性)

题解: 首先裸dp方程为: F(x)=a*x*x+b*x+c;  sum为前缀和 f[i]=f[j]+F(sum[i]-sum[j]); 然后拆开后把带j的放一边,带i的放一边,形成y=kx+b的形式,使y和x都含j不含i,k和b都含i不含j. 得:f[j]+asum[j]*sum[j]-b*sum[j]=2*a*sum[i]*sum[j]+f[i]-a*sum[i]*sum[i]-b*sum[i]-c; 然后有:y=kx+b; y=f[j]+asum[j]*sum[j]-b*sum[j]; x

HDU 1520 树形dp裸题

1.HDU 1520  Anniversary party 2.总结:第一道树形dp,有点纠结 题意:公司聚会,员工与直接上司不能同时来,求最大权值和 #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #define max(a,b) a>b?a:b using nam

hdu 2993 MAX Average Problem(斜率DP入门题)

题目链接:hdu 2993 MAX Average Problem 题意: 给一个长度为 n 的序列,找出长度 >= k 的平均值最大的连续子序列. 题解: 这题是论文的原题,请参照2004集训队论文<周源--浅谈数形结合思想在信息学竞赛中的应用> 这题输入有点大,要加读入优化才能过. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 5