hdu 3480 Division(斜率优化DP)
题目链接:hdu 3480 Division
题意:
给你一个有n个数的集合S,现在让你选出m个子集合,使这m个子集合并起来为S,并且每个集合的(max-min)2 之和要最小。
题解:
运用贪心的思想,肯定首先将全部的数排好序,然后设dp[i][j]表示前j个数分为i个集合的最优解。
则有dp[i][j]=min{dp[i-1][k]+(a[j]-a[k+1])2}(0<k<j)。
这样写出来是三层for的dp,考虑用斜率优化降维。
假设l<k<j,对于dp[i][j],k到j为一个集合比l到j为一个集合更优。
则有:dp[i-1][k]+(a[j]-a[k+1])2<=dp[i-1][l]+(a[j]-a[l+1])2。
整理得 dp[i-1][k]+a[k+1]2 -dp[i-1][l]+a[l+1]2 /a[k+1]-a[l-1]<=2*a[j]。
然后就是y1-y2/x1-x2<=L的斜率形式了。
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 5 const int N=10007; 6 7 int t,n,m,dp[2][N],Q[N],a[N],ic; 8 9 int getx(int k,int l){return a[k+1]-a[l+1];} 10 int gety(int i,int k,int l){return dp[i][k]+a[k+1]*a[k+1]-dp[i][l]-a[l+1]*a[l+1];} 11 int check(int i,int j,int k,int l){return gety(i,j,k)*getx(k,l)<=gety(i,k,l)*getx(j,k);} 12 13 int main() 14 { 15 scanf("%d",&t); 16 while(t--) 17 { 18 scanf("%d%d",&n,&m); 19 F(i,1,n)scanf("%d",a+i); 20 sort(a+1,a+1+n); 21 F(i,1,n)dp[0][i]=(a[i]-a[1])*(a[i]-a[1]); 22 F(i,2,m) 23 { 24 int now=0,head=1,tail=0; 25 Q[++tail]=i-1; 26 F(j,i,n) 27 { 28 while(head<tail&&check(i&1,j,Q[tail],Q[tail-1]))tail--;//维护一个“下凸”曲线 29 Q[++tail]=j; 30 while(head<tail&&gety(i&1,Q[head+1],Q[head])<=getx(Q[head+1],Q[head])*2*a[j])head++; 31 dp[(i&1)^1][j]=dp[i&1][Q[head]]+(a[j]-a[Q[head]+1])*(a[j]-a[Q[head]+1]); 32 } 33 } 34 printf("Case %d: %d\n",++ic,dp[(m&1)^1][n]); 35 } 36 return 0; 37 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· DeepSeek火爆全网,官网宕机?本地部署一个随便玩「LLM探索」
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(三):用.NET IoT库
· 上周热点回顾(1.20-1.26)