[HDU3480] Division [四边形不等式dp]

题面:

传送门

思路:

因为集合可以无序选择,所以我们先把输入数据排个序

然后发先可以动归一波

设$dp\left[i\right]\left[j\right]$表示前j个数中分了i个集合,$w\left(i\right)\left(j\right)$表示$i$到$j$的闭区间分到一个集合里的花费

然后就有方程式:

$dp\left[i\right]\left[j\right]=min\left(dp\left[i-1\right]\left[k-1\right]+w\left(k\right)\left(j\right)\right)$

可是这道题$n=10000,m=5000$,目测这样跑区间$dp$时间复杂度依然很捉急啊

没关系,我们请出四边形不等式优化

容易证明,$w$函数满足四边形不等式,同时满足区间单调性

因此$dp$函数也满足四边形不等式,可以优化

优化完以后是$O\left(nm\right)$的效率,AC~

 

Code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 unsigned int inf=0x7fffffff;
 6 using namespace std;
 7 inline int read(){
 8     int re=0,flag=1;char ch=getchar();
 9     while(ch>'9'||ch<'0'){
10         if(ch=='-') flag=-1;
11         ch=getchar();
12     }
13     while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
14     return re*flag;
15 }
16 int n,m,a[10010];
17 unsigned int dp[5010][10010];short s[5010][10010];
18 unsigned int w(int l,int r){
19     return (a[l]-a[r])*(a[l]-a[r]);
20 }
21 int main(){
22     int i,j,k,len,T=read(),cnt=0;unsigned tmp;
23     while(T--){
24         n=read();m=read();
25         for(i=1;i<=n;i++) a[i]=read();
26         sort(a+1,a+n+1);
27         for(i=0;i<=m;i++) dp[i][i]=0,s[i][i]=i;
28         for(i=m+1;i<=n;i++) s[m+1][i]=i;
29         for(len=1;len<n;len++){
30             dp[0][len]=inf;
31             for(i=1;i<=m;i++){
32                 j=i+len;if(j>n) break;
33                 dp[i][j]=inf;
34                 for(k=s[i][j-1];k<=s[i+1][j];k++){
35                     if((tmp=dp[i-1][k-1]+w(k,j))<dp[i][j]){
36                         dp[i][j]=tmp;s[i][j]=k;
37                     }
38                 }
39             }
40         }
41         printf("Case %d: %d\n",++cnt,dp[m][n]);
42     }
43 }

 

posted @ 2018-03-17 22:01  dedicatus545  阅读(198)  评论(0编辑  收藏  举报