HDOJ 3480 Division

斜率优化DP。。。。

对数组排序后,dp【i】【j】表示对前j个物品分i段的最少代价,dp【i】【j】= min{ dp【i-1】【k】+(a【k+1】-a【j】)^2 }复杂度m*n^2      斜率优化一下就可以了。

Division

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 999999/400000 K (Java/Others)

Total Submission(s): 3008    Accepted Submission(s): 1173

Problem Description

Little D is really interested in the theorem of sets recently. There’s a problem that confused him a long time.

Let T be a set of integers. Let the MIN be the minimum integer in T and MAX be the maximum, then the cost of set T if defined as (MAX – MIN)^2. Now given an integer set S, we want to find out M subsets S1, S2, …, SM of S, such that

and the total cost of each subset is minimal.

Input

The input contains multiple test cases.

In the first line of the input there’s an integer T which is the number of test cases. Then the description of T test cases will be given.

For any test case, the first line contains two integers N (≤ 10,000) and M (≤ 5,000). N is the number of elements in S (may be duplicated). M is the number of subsets that we want to get. In the next line, there will be N integers giving set S.

Output

For each test case, output one line containing exactly one integer, the minimal total cost. Take a look at the sample output for format.

Sample Input

2
3 2
1 2 4
4 2
4 7 10 1

Sample Output

Case 1: 1
Case 2: 18

Hint

The answer will fit into a 32-bit signed integer.

Source

2010
ACM-ICPC Multi-University Training Contest(5)——Host by BJTU

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn=11000;

int n,m;
int dp[maxn/2][maxn],a[maxn];
int q[maxn],head,tail;

int main()
{
	int T_T,cas=1;
	scanf("%d",&T_T);
	while(T_T--)
	{
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
			scanf("%d",a+i);
		sort(a+1,a+n+1);
		for(int i=1;i<=n;i++)
			dp[1][i]=(a[i]-a[1])*(a[i]-a[1]);
		for(int i=2;i<=m;i++)
		{
		    head=tail=0;
		    q[tail++]=i-1;
		    for(int j=i;j<=n;j++)
            {
                while(head+1<tail)
                {
                    int p1=q[head];
                    int p2=q[head+1];
                    int x1=a[p1+1],x2=a[p2+1];
                    int y1=dp[i-1][p1]+x1*x1;
                    int y2=dp[i-1][p2]+x2*x2;
                    if((y2-y1)<=(x2-x1)*2*a[j]) head++;
                    else break;
                }
                int k=q[head];
                dp[i][j]=dp[i-1][k]+(a[k+1]-a[j])*(a[k+1]-a[j]);
                while(head+1<tail)
                {
                    int p1=q[tail-2],p2=q[tail-1],p3=j;
                    int x1=a[p1+1],x2=a[p2+1],x3=a[p3+1];
                    int y1=dp[i-1][p1]+x1*x1;
                    int y2=dp[i-1][p2]+x2*x2;
                    int y3=dp[i-1][p3]+x3*x3;
                    if((y3-y2)*(x2-x1)<=(y2-y1)*(x3-x2)) tail--;
                    else break;
                }
                q[tail++]=j;
            }
		}
		printf("Case %d: %d\n",cas++,dp[m][n]);
    }
	return 0;
}

HDOJ 3480 Division

时间: 2024-11-12 08:58:47

HDOJ 3480 Division的相关文章

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 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

【HDU】3480 Division

http://acm.hdu.edu.cn/showproblem.php?pid=3480 题意:一个n个元素的集合S要求分成m个子集且子集并为S,要求$\sum_{S_i} (MAX-MIN)^2$最小.(n<=10000, m<=5000) #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <iostream>

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++可能会超时. 代码:

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 DP + 四边形优化

水题,证明有单调性之后直接照着拍就好 #include <cstdio> #include <cstring> #include <algorithm> #include <climits> using namespace std; #define sq(x) ((x)*(x)) const int maxn = 10005; const int maxm = 5005; int f[maxn][maxm], s[maxn][maxm]; int val[m

HDU 3480 division

题目大意:一个有n个数的集合,现在要求将他分成m+1个子集,对子集i设si表示该集合中最大数与最小数的差的平方.求所有si的和的最小值.n<=10000,m<=5000. 分析:最优解的m个集合肯定不会相交,也不会出现空集,而且每个子集的数必定是连续的. 所以可以将n个数先排序,在来进行dp求解. f[i][j]表示前j个数分成i个集合的最优解. 转移方程为:f[i][j]=min(f[i-1][k]+(num[j]-num[k+1])^2 设决策点k1<k2,若有k2比k1更优,则有:

hdu 3480 Division(四边形不等式优化)

Problem Description Little D is really interested in the theorem of sets recently. There’s a problem that confused him a long time.  Let T be a set of integers. Let the MIN be the minimum integer in T and MAX be the maximum, then the cost of set T if

【HDOJ】【3480】Division

DP/四边形不等式 要求将一个可重集S分成M个子集,求子集的极差的平方和最小是多少…… 首先我们先将这N个数排序,容易想到每个自己都对应着这个有序数组中的一段……而不会是互相穿插着= =因为交换一下明显可以减小极差 然后……直接四边形不等式上吧……这应该不用证明了吧? MLE了一次:这次的w函数不能再开数组去存了……会爆的,直接算就行了= =反正是知道下标直接就能乘出来. 数据比较弱,我没开long long保存中间结果居然也没爆……(只保证最后结果不会爆int,没说DP过程中不会……) 1 /