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)
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
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元素的集合S,选取M个S的子集,要求满足S1 U S2 U … U SM = S;
定义一个集合的最大元素为MAX,最小元素为MIN,它的花费为(MAX - MIN)2,现要求所有子集的总花费最少为多少。
题解:
先将S内元素从小到大排列,然后将这N个元素的序列分成M组(因为若有重叠元素,必然会使得花费增加);
那么假设dp[i][j]为前i个数分成j组的最小花费,那么求出dp[N][M]即可回答问题;
状态转移方程为dp[i][j] = min{ dp[k][j-1] + (S[i] - S[k+1])2 },j-1≤k<i;
那么当j固定时,计算dp[i][j]时需要枚举k,若k可能取值到a,b两点,且j-1≤a<b<i,
若有 dp[b][j-1] + (S[i] - S[b+1])2 ≤ dp[a][j-1] + (S[i] - S[a+1])2,则b点优于a点;
将上式变形,得到:
b点优于a点 <=>
再然后就是斜率优化的老套路了(斜率优化的详情查看斜率DP分类里之前的文章),就不再赘述。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=+; int n,m,S[maxn];
int dp[maxn][maxn];
int q[maxn],head,tail; int up(int a,int b,int j) //g(a,b)的分子部分
{
return (dp[b][j-]+S[b+]*S[b+])-(dp[a][j-]+S[a+]*S[a+]);
}
int down(int a,int b) //g(a,b)的分母部分
{
return *S[b+]-*S[a+];
} int main()
{
int t;
scanf("%d",&t);
for(int kase=;kase<=t;kase++)
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%d",&S[i]);
sort(S+,S+n+); for(int i=;i<=n;i++) dp[i][]=(S[i]-S[])*(S[i]-S[]);
for(int j=;j<=m;j++)
{
head=tail=;
q[tail++]=j-;
for(int i=j;i<=n;i++)
{
while(head+<tail)
{
int a=q[head], b=q[head+];
if(up(a,b,j)<=S[i]*down(a,b)) head++; //g(a,b)<=S[i]
else break;
}
int k=q[head];
dp[i][j]=dp[k][j-]+(S[i]-S[k+])*(S[i]-S[k+]); while(head+<tail)
{
int a=q[tail-], b=q[tail-];
if(up(a,b,j)*down(b,i)>=up(b,i,j)*down(a,b)) tail--; //g(a,b)>=g(b,i)
else break;
}
q[tail++]=i;
}
} printf("Case %d: %d\n",kase,dp[n][m]);
}
}
注意DP边界的初始化。
HDU 3480 - Division - [斜率DP]的更多相关文章
- hdu 3480 Division(斜率优化DP)
题目链接:hdu 3480 Division 题意: 给你一个有n个数的集合S,现在让你选出m个子集合,使这m个子集合并起来为S,并且每个集合的(max-min)2 之和要最小. 题解: 运用贪心的思 ...
- HDU 2829 - Lawrence - [斜率DP]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2829 T. E. Lawrence was a controversial figure during ...
- ACM-ICPC 2016 沈阳赛区现场赛 I. The Elder && HDU 5956(斜率DP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5956 题意:一颗树上每条边有个权值,每个节点都有新闻要送到根节点就是1节点,运送过程中如果不换青蛙就是 ...
- HDU 3480 Division(斜率DP裸题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3480 题目大意:将n个数字分成m段,每段价值为(该段最大值-该段最小值)^2,求最小的总价值. 解题思 ...
- HDU 3480 Division(斜率优化+二维DP)
Division Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 999999/400000 K (Java/Others) Tota ...
- HDU 3480 Division DP斜率优化
解题思路 第一步显然是将原数组排序嘛--然后分成一些不相交的子集,这样显然最小.重点是怎么分. 首先,我们写出一个最暴力的\(DP\): 我们令$F[ i ][ j ] $ 为到第\(i\)位,分成\ ...
- HDU 3480 division
题目大意:一个有n个数的集合,现在要求将他分成m+1个子集,对子集i设si表示该集合中最大数与最小数的差的平方.求所有si的和的最小值.n<=10000,m<=5000. 分析:最优解的m ...
- hdu 3480 Division(四边形不等式优化)
Problem Description Little D is really interested in the theorem of sets recently. There’s a problem ...
- hdu 2829 Lawrence(斜率优化DP)
题目链接:hdu 2829 Lawrence 题意: 在一条直线型的铁路上,每个站点有各自的权重num[i],每一段铁路(边)的权重(题目上说是战略价值什么的好像)是能经过这条边的所有站点的乘积之和. ...
随机推荐
- easyui datagrid 单元格编辑(cell editing)
demo中有row editing 项目中发现个cell editing,但是有bug,修改好了 主要实现功能:单击数据表格单元格,编辑单元格数据 js代码如下: $.extend($.fn.data ...
- 记安装ubuntu server和一些程序
1. 安装ubuntu server 按照流程走了一遍,一切画面都正常,就是重启后界面只有一个光标闪啊闪,我不知道应该再装一遍还是找老大来解决,想了下,以前电脑就是因为出错才重装的,现在这个情况有可能 ...
- (转)base64编码是怎么工作的?
按:在PHP中级班的课堂上,有位同学问这样一个问题:“我在用 base64_encode 对用户名进行编码时,会出来等号,是不是可以去掉?”跟我来看完这篇文章,答案即揭晓. 1: 为什么需要base6 ...
- PHP计算两个绝对路径的相对路径
用PHP计算两个绝对路径的相对路径,该如何求呢? 先根据分隔符切割,然后查找相同 异同点,然后开始有相同点,从相同点结束为止开始拼接剩余部分,没有的话,到达根路径拼接整体. 截图如下: 代码如下: & ...
- ios开发之--通过通知监听textfield的输入状态,判断按钮的状态
第一步: _rightBtn = [UIButton buttonWithType:UIButtonTypeCustom]; _rightBtn.frame = CGRectMake(kWidth - ...
- 【Python】Excel处理
1.包导入 from openpyxl import Workbook from openpyxl import load_workbook from openpyxl.compat import r ...
- Redis 未授权访问漏洞(附Python脚本)
0x01 环境搭建 #下载并安装 cd /tmp wget http://download.redis.io/releases/redis-2.8.17.tar.gz tar xzf redis-.t ...
- N76E003之SPI
串行外围总线 (SPI)N76E003系列提供支持高速串行通信的SPI模块.SPI 为微控制与外设 EEPROM, LCD 驱动, D/A 转换之间提供全双工.高速.同步传输的总线.可提供主机从机模式 ...
- 安装ubuntu后,你的屏幕尺寸太小,无法设置,该怎么解决
安装完虚拟机之后,你的Ubuntu可能会在尺寸很小,(这种情况可能有,可能没有) 想要点击设置,选中Display里的分辨率下拉框,但是却因为这个窗口太大,无法点击apply按钮.悲剧啦!!! Ctr ...
- 升级nodejs至最新
网上找出了很多升级nodejs版本的方法,都不太好用,直至发现这个: 在命令行窗口中执行:where node: 然后在nodejs官网中下载最新版本,将刚才目录下node.exe替换掉: 最后执行: ...