hdu 3480 Division

來源:互聯網
上載者:User
Division

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 999999/400000 K (Java/Others)
Total Submission(s): 2066    Accepted Submission(s): 817

Problem DescriptionLittle 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.

 

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

 

OutputFor 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

23 21 2 44 24 7 10 1
 

Sample Output

Case 1: 1Case 2: 18HintThe answer will fit into a 32-bit signed integer. 
 

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

Recommendzhengfeng題意:給你一個含n個元素集合。要你把它分成m個子集。要使它們價值最小。價值即每個集合中的最大元素減最小元素的平方求和。思路:為了使連續區間最大值減最小值最小所以先從大到小排序。然後就很好得到轉移方程了。dp[i][j]代表前i個元素分成j個子集的最小价值。1<=j<=i。dp[i][j]=MIN(dp[k][j-1]+(a[i]-a[k+1])^2)。1<=k<i且k>=j-1。直接枚舉k肯定是要逾時的,開始想到了用單調隊列最佳化。結果發現轉移方程中有a[i]所以結果與a[i]有關單調隊列肯定是不行了。於是想能不能用斜率最佳化或者四邊形不等式什麼的。於是耐著性子把方程展開:dp[i][j]=MIN(dp[k][j-1]+a[i]^2+a[k+1]^2-2*a[i]*a[k+1])。設r>k。設f(k)=dp[k][j-1]+a[i]^2+a[k+1]^2-2*a[i]*a[k+1]。f(r)-f(k)=dp[r][j-1]+a[r+1]^2-a[k+1]^2-2*a[i]*(a[r+1]-a[k+1])令f(r)-f(k)<=0令y=dp[x][j-1]+a[x+1]^2。x=a[x+1]。那麼(y(r)-y(k))/(xr-xk)<=2*a[i]。y與x就與a[i]無關了。可以使用斜率最佳化斜率小於2*a[i]說明r更優。

#include <iostream>#include<stdio.h>#include<string.h>#include<algorithm>#define MAX(a,b) ((a)>(b)?(a):(b))#define MIN(a,b) ((a)<(b)?(a):(b))#define positive(a) ((a)>0?(a):-(a))using namespace std;int a[10010],dp[10010][5010];//a存數值。dp[i][j]表示前i個元素分成j個子集的最小价值int n,m,head,tail;int q[10010];//隊列int main(){    int t,cas,i,j,k,x1,x2,x3,y1,y2,y3,p1,p2,p3;    scanf("%d",&t);    for(cas=1;cas<=t;cas++)    {        scanf("%d%d",&n,&m);        for(i=1;i<=n;i++)            scanf("%d",a+i);        sort(a+1,a+n+1);        for(i=1;i<=n;i++)        {            dp[i][1]=(a[i]-a[1])*(a[i]-a[1]);//一個子集即自己本身            dp[i][i]=0;//全為資料格集價值為0        }        for(j=2;j<=m;j++)        {            head=tail=0;            q[tail++]=j-1;//k的範圍為j-1<=k<i所以先入隊兩個元素            q[tail++]=j;            for(i=j+1;i<=n;i++)            {                while(tail-head>=2)                {                    p1=q[head];                    p2=q[head+1];                    y1=dp[p1][j-1]+a[p1+1]*a[p1+1];                    x1=a[p1+1];                    y2=dp[p2][j-1]+a[p2+1]*a[p2+1];                    x2=a[p2+1];                    if(y2-y1<=2*a[i]*(x2-x1))//(y2-y1)/(x2-x1)<=2*a[i]說明y2更優所以去掉y1                        head++;                    else                        break;                }                k=q[head];                dp[i][j]=dp[k][j-1]+(a[i]-a[k+1])*(a[i]-a[k+1]);                while(tail-head>=2)//加入i去掉上凸點                {                    p1=q[tail-2];                    p2=q[tail-1];                    p3=i;                    y3=dp[p3][j-1]+a[p3+1]*a[p3+1];                    x3=a[p3+1];                    y2=dp[p2][j-1]+a[p2+1]*a[p2+1];                    x2=a[p2+1];                    y1=dp[p1][j-1]+a[p1+1]*a[p1+1];                    x1=a[p1+1];                    if((y3-y2)*(x2-x1)<=(y2-y1)*(x3-x2))                        tail--;                    else                        break;                }                q[tail++]=i;            }        }        printf("Case %d: %d\n",cas,dp[n][m]);    }    return 0;}
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.