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

题意:求n个数分成m个集合 要求花费的最小值

思路:我们首先要求出状态转移方程dp[i][j]=min(dp[i][j],dp[k][j-1]+(a[i]-a[k+1])^2) 这里我们可以用四边形不等式优化(打表可知)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define ll long long int
using namespace std;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
int moth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int dir[4][2]={1,0 ,0,1 ,-1,0 ,0,-1};
int dirs[8][2]={1,0 ,0,1 ,-1,0 ,0,-1, -1,-1 ,-1,1 ,1,-1 ,1,1};
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
int dp[10007][5007]; //dp[i][j] 表示前i个人 分组成j组
int s[10007][5007]; //决策数组
int a[10007];
int main(){
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    int w=0;
    while(t--){
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        sort(a+1,a+1+n); //排序后满足一个区间内的值是首尾的差平方
        for(int i=1;i<=n;i++){ //初始化边界
            dp[i][1]=(a[i]-a[1])*(a[i]-a[1]); //前i个人分成1组
            s[i][1]=1; //初始化决策数组的左边界
        }
        for(int j=2;j<=m;j++){
            s[n+1][j]=n-1; //初始化决策数组的右边界
            for(int i=n;i>=j;i--){
                dp[i][j]=inf;
                for(int k=s[i][j-1];k<=s[i+1][j];k++){ //四边形不等式优化
                    if(dp[i][j]>dp[k][j-1]+(a[i]-a[k+1])*(a[i]-a[k+1])){
                        dp[i][j]=dp[k][j-1]+(a[i]-a[k+1])*(a[i]-a[k+1]);
                        s[i][j]=k;
                    }
                }
            }
        }
        cout<<"Case "<<++w<<": ";
        cout<<dp[n][m]<<endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/wmj6/p/10714337.html

时间: 2024-08-18 14:08:16

hdu 3480 Division(四边形不等式优化)的相关文章

hdu 3480 dp 四边形不等式优化

http://acm.hdu.edu.cn/showproblem.php?pid=3480 给出一个数字集合 S,大小为 n,要求把这个集合分成m个子集,每分出一个子集的费用是子集中的 (max-min)^2,求最小费用. 开始的dp转移很容易想到. 首先对集合从小到大排序,dp[i][j] 表示前i个元素被分成j个子集的最小费用.然后枚举最后一个子集. dp[i][j] = min{dp[k-1][j-1] + cost(k, i)}; 这个转移明显是过不去的,n<10000 m<5000

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 3516 DP 四边形不等式优化 Tree Construction

设d(i, j)为连通第i个点到第j个点的树的最小长度,则有状态转移方程: d(i, j) = min{ d(i, k) + d(k + 1, j) + p[k].y - p[j].y + p[k+1].x - p[i].x } 然后用四边形不等式优化之.. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <

hdu 2829 dp+四边形不等式优化

用w[i][j]表示i到j之间没有边毁掉的费用. 有一种很好证明w[i][j]是否满足四边形不等式的条件. 若(w[i+1][j]-w[i][j])是关于j的减函数,就是满足条件的.可以证明这里的w[i][j]是瞒住条件的. #include <set> #include <map> #include <queue> #include <stack> #include <cmath> #include <string> #includ

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 3506 DP 四边形不等式优化 Monkey Party

环形石子合并问题. 有一种方法是取模,而如果空间允许的话(或者滚动数组),可以把长度为n个换拓展成长为2n-1的直线. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace std; 7 8 const int maxn = 2000 + 10; 9 const int INF = 0x3f3f3f3f

HDU 2829 Lawrence (斜率优化DP或四边形不等式优化DP)

题意:给定 n 个数,要你将其分成m + 1组,要求每组数必须是连续的而且要求得到的价值最小.一组数的价值定义为该组内任意两个数乘积之和,如果某组中仅有一个数,那么该组数的价值为0. 析:DP状态方程很容易想出来,dp[i][j] 表示前 j 个数分成 i 组.但是复杂度是三次方的,肯定会超时,就要对其进行优化. 有两种方式,一种是斜率对其进行优化,是一个很简单的斜率优化 dp[i][j] = min{dp[i-1][k] - w[k] + sum[k]*sum[k] - sum[k]*sum[

【转】斜率优化DP和四边形不等式优化DP整理

当dp的状态转移方程dp[i]的状态i需要从前面(0~i-1)个状态找出最优子决策做转移时 我们常常需要双重循环 (一重循环跑状态 i,一重循环跑 i 的所有子状态)这样的时间复杂度是O(N^2)而 斜率优化或者四边形不等式优化后的DP 可以将时间复杂度缩减到O(N) O(N^2)可以优化到O(N) ,O(N^3)可以优化到O(N^2),依次类推 斜率优化DP和四边形不等式优化DP主要的原理就是利用斜率或者四边形不等式等数学方法 在所有要判断的子状态中迅速做出判断,所以这里的优化其实是省去了枚举

四边形不等式优化

四边形不等式优化条件(转自这里) 在动态规划中,经常遇到形如下式的转台转移方程: m(i,j)=min{m(i,k-1),m(k,j)}+w(i,j)(i≤k≤j)(min也可以改为max) 上述的m(i,j)表示区间[i,j]上的某个最优值.w(i,j)表示在转移时需要额外付出的代价.该方程的时间复杂度为O(N^3). 下面我们通过四边形不等式来优化上述方程,首先介绍什么是"区间包含的单调性"和"四边形不等式" (1)区间包含的单调性:如果对于i≤i'<j≤