codeforces 572D Minimization
2015-09-18 21:29
465 查看
题目链接:http://codeforces.com/problemset/problem/572/D
当k=1的时候,从小到大排序求相邻差值的和,那就是最小值
当k>1的时候,先看个例子
数列1 4 5 8 10 k=2
那么相邻的差值之和就是10
那么可以分成2个数字一段,3个数字一段
如果结果是1 4 5 8 10 最终的差值和就是10-3=7
如果结果是1 4 5 8 10 最终的差值和就是10-1=9
用dp做
dp[i][j] i表示总的段数 j表示较短的段数
当k=1的时候,从小到大排序求相邻差值的和,那就是最小值
当k>1的时候,先看个例子
数列1 4 5 8 10 k=2
那么相邻的差值之和就是10
那么可以分成2个数字一段,3个数字一段
如果结果是1 4 5 8 10 最终的差值和就是10-3=7
如果结果是1 4 5 8 10 最终的差值和就是10-1=9
用dp做
dp[i][j] i表示总的段数 j表示较短的段数
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <string> using namespace std; #define inf 300005 #define ll __int64 ll p[inf]; ll dp[5001][5001]; int main() { int n,k; memset(p,0,sizeof(p)); memset(dp,0,sizeof(dp)); scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) { scanf("%I64d",&p[i]); } sort(p+1,p+1+n); ll sum=0; for(int i=2;i<=n;i++) { sum+=p[i]-p[i-1]; } int n1,n2,num1,num2; n1=n/k;//较短一段的数字的个数 n2=n/k+min(1,n%k);//较长一段的数字的个数 num2=n%k;//较长一段的段数 num1=(n-num2*n2)/n1;//较短一段的段数 ll ans=0; for(int i=1;i<num1;i++) { ans+=p[i*n1+1]-p[i*n1]; dp[i][i]=ans; } if(num2>0) { dp[num1][num1]=ans+p[num1*n1+1]-p[num1*n1]; } if(num2==0) dp[num1][num1]=ans; else { for(int i=1;i<=num1+num2;i++) { for(int j=max(0,i-num2);j<=min(i,num1);j++) { if(i==j) { continue; } ll ans=p[(i-j)*n2+j*n1+1]-p[(i-j)*n2+j*n1]; if(ans<0) ans=0; dp[i][j]=dp[i-1][j]+ans; if(j>=1 && i-j<=num2) { dp[i][j]=max(dp[i][j],dp[i-1][j-1]+ans); } } } } printf("%I64d\n",sum-dp[num1+num2][num1]); return 0; }
相关文章推荐
- 【leetcode】No.33 Search in Rotated Sorted Array
- 黑马程序员-----------static关键字
- 最大子段和【模板】
- PS修改寸照背景色
- eclipse 流畅优化利器
- trie+dp
- POJ 3579- Median
- 复选框全选、全不选和反选的效果实现
- 源码编译安装vsftpd3.0.2
- Java设置全局热键钩子——第三方包jintellitype实现
- 欢迎使用CSDN-markdown编辑器
- Android 自定义View——蒙版擦除效果实现
- 51nod 1232 完美数 / codeforces 55D 数位DP
- HDU4167
- UITableView(表视图)使用详解
- android selector 小坑
- Manacher算法
- Smarty 时间 格式
- 欧拉函数
- php连接sqlserver