HDU 3392 Pie(DP)
题意:有一些男生女生,男生女生数量差不超过100 ,男生女生两两配对。要求求出一种配对方法,使每一对的高度差的和最小。
思路:(我是真的笨笨笨!!)设人少的一组人数为n,b[],人多的一组人数为m,g[](b[],g[]先排好序),用dp[i][j]表示n中的前i个人与m中的前j个人配对所得到的最小值。
对于每个i,j的范围是(i~i+m-n)

这样j的范围是i~m-n+i,对于dp数组而言,第二维数组要开到m,由于数组过大,而我们又知道,m-n<=100,所以用j表示j-i,j的范围就变成了(0~m-n),也就是(0~100),这种情况下dp[i][j]表示b中前i个人和g中前i+j个人的最小值。
对于每一个dp[i][j]它的可能就是选第i+j个,不选第i+j个数。
如果不选的话,那么dp[i][j]就等于dp[i][j-1],如果选了呢,就是dp[i-1][j]+|b[i]-g[i+j]|
状态转移方程:dp[i][j]=min(dp[i][j-1], dp[i-1][j] + |b[i]-g[i+j]|)
AC代码:
/** hdu 3392 */ #include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std; const int N = 10005;
double a[N], b[N];
double dp[N][110]; double getdp(int m, int n, double *g, double *b)
//m,g为人数多的一组,n,b为人少的一组
{
for (int i = 1; i <= n; ++i) {
dp[i][0] = dp[i - 1][0] + fabs(b[i] - g[i]);//对于dp[...][0],即两组个数相等,没有选择~
for (int j = 1; j <= m - n; ++j) {
dp[i][j] = min(dp[i - 1][j] + fabs(b[i] - g[i + j]), dp[i][j - 1]);
}
}
return dp[n][m - n];
} int main()
{
//freopen("in.txt", "r", stdin);
int boys, girls;
while (scanf("%d%d", &boys, &girls) != EOF && (boys || girls)) {
for (int i = 1; i <= boys; i++) {
scanf("%lf", &a[i]);
}
for (int i = 1; i <= girls; i++) {
scanf("%lf", &b[i]);
}
sort(a + 1, a + 1 + boys);
sort(b + 1, b + 1 + girls);
double ans;
if (boys < girls)
ans = getdp(girls, boys, b, a);
else
ans = getdp(boys, girls, a, b);
printf("%f\n", ans);
}
return 0;
}
但是看了别人的博客,可以用到滚动数组【啊喂!!我就是为了学一下滚动数组才搜到这道题的,结果根本不用啊!】。
滚动数组很神奇啊,因为对于每一个dp[i],求它的过程只与dp[i-1]有关,所以开成2个就够了。既dp[2][...]
代码
/** hdu 3392 */ const int N = 10005;
double a[N], b[N];
double dp[2][110]; double getdp(int m, int n, double *g, double *b)
//m,g为人数多的一组,n,b为人少的一组
{
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; ++i) {
dp[i % 2][0] = dp[(i - 1) % 2][0] + fabs(b[i] - g[i]);
for (int j = 1; j <= m - n; ++j) {
dp[i % 2][j] = min(dp[(i - 1) % 2][j] + fabs(b[i] - g[i + j]), dp[i % 2][j - 1]);
}
}
return dp[n % 2][m - n];
}
改了之后注意加一句memset(dp, 0, sizeof(dp));
因为窝之前的dp[0][..]是没有用到的,一直是0……所以不用
对于这种通过%N...来节省数组空间的方法窝觉得真是太神奇了orz……
继续努力~
HDU 3392 Pie(DP)的更多相关文章
- hdu 3392(滚动数组优化dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3392 Pie Time Limit: 6000/3000 MS (Java/Others) Me ...
- hdu 4123 树形DP+RMQ
http://acm.hdu.edu.cn/showproblem.php? pid=4123 Problem Description Bob wants to hold a race to enco ...
- hdu 4507 数位dp(求和,求平方和)
http://acm.hdu.edu.cn/showproblem.php?pid=4507 Problem Description 单身! 依旧单身! 吉哥依旧单身! DS级码农吉哥依旧单身! 所以 ...
- hdu 3709 数字dp(小思)
http://acm.hdu.edu.cn/showproblem.php?pid=3709 Problem Description A balanced number is a non-negati ...
- hdu 4352 数位dp + 状态压缩
XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- hdu 4283 区间dp
You Are the One Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化
HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化 n个节点n-1条线性边,炸掉M条边也就是分为m+1个区间 问你各个区间的总策略值最少的炸法 就题目本身而言,中规中矩的 ...
- HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化)
HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化) 题意分析 先把每种硬币按照二进制拆分好,然后做01背包即可.需要注意的是本题只需要求解可以凑出几种金钱的价格,而不需要输出种数 ...
- HDOJ(HDU).1059 Dividing(DP 多重背包+二进制优化)
HDOJ(HDU).1059 Dividing(DP 多重背包+二进制优化) 题意分析 给出一系列的石头的数量,然后问石头能否被平分成为价值相等的2份.首先可以确定的是如果石头的价值总和为奇数的话,那 ...
随机推荐
- C# zip/unzip with DotNet framework 4.5
add reference System.IO.Compression.FileSystem public class ZipHelper { public static string UnZip(s ...
- JavaScript trim 实现(去除字符串首尾指定字符)
String.prototype.trim = function (char, type) { if (char) { if (type == 'left') { return this.replac ...
- <三> jQuery 选择器
jQuery 选择器选择需要应用效果的元素,jQuery 元素选择器和属性选择器允许您通过标签名.属性名或内容对 HTML 元素进行选择.选择器允许您对 HTML 元素组或单个元素进行操作. 元素选择 ...
- Elasticsearch基础概念理解
熟悉ES中的几个关键概念: 节点(Node):一个elasticsearch运行的实例,其实就是一个java进程.一般情况下,一台机器运行在一台机器上. 集群(Cluster): 好几个有相同集群名称 ...
- 在安装MySQL Workbentch的时候出现如下问题,已经解决。
mysql workbench cannot be executed from a path that contains non-ASCII characters. this problem is i ...
- 查看linux系统的版本
1. 查看内核版本命令: 1) [root@SOR_SYS ~]# cat /proc/version Linux version 2.6.18-238.el5 (mockbuild@x86-012. ...
- linux命令ps aux|grep xxx详解
对进程进行监测和控制,首先必须要了解当前进程的情况,也就是需要查看当前进程, 而ps命令(Process Status)就是最基本同时也是非常强大的进程查看命令. 使用该命令 可以确定有哪些进程正在运 ...
- 李洪强漫谈iOS开发[C语言-018]-scanf函数
- CC_UNUSED_PARAM 宏含义的解释
#define CC_UNUSED_PARAM(unusedparam) (void)unusedparam 这个宏完全没有执行任何命令,这样写的原因主要是历史遗留原因,ojb-c不存在纯虚函数并且传 ...
- leetcode面试准备: Word Pattern
leetcode面试准备: Word Pattern 1 题目 Given a pattern and a string str, find if str follows the same patte ...