HDU 3392 Pie(DP+滚动数组)

题意:有一些男生女生,男生女生数量差不超过100 ,男生女生两两配对。要求求出一种配对方法,使每一对的高度差的和最小。

思路:(我是真的笨笨笨!!磨磨唧唧写一堆是因为我笨!我看了别人的博客,思路全是学别人的,轻喷!)设人少的一组人数为n,b[],人多的一组人数为m,g[](b[],g[]先排好序),用dp[i][j]表示n中的前i个人与m中的前j个人配对所得到的最小值。

那么dp[i][j]就是min(dp[i-1][k]+|b[i]-g[k]|),就是n中前i-1个人和m中前1~k个人配对的最小值加上b[i]和g[k]的差。

对于每个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个人的最小值。

好了,这样就好写了。

代码是

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]);
        for (int j = 1; j <= m - n; ++j) {
            dp[i][j] = dp[i - 1][0] + fabs(b[i] - g[i]);
            for (int k = 1; k <= j; k++) {
                dp[i][j] = min(dp[i][j], dp[i - 1][k] + fabs(b[i] - g[i + k]));
            }
        }
    }
    return dp[n][m - n];
}

好了,提交一下TLE……拜托,这也能叫dp?我已经学蒙了orz

看一下时间复杂度是n*(m-n)^2,超时妥妥滴……

这时换一个思路,就是对于每一个dp[i][j]它的可能就是选第i+j个,不选第i+j个数。

如果不选的话,那么dp[i][j]就等于dp[i][j-1]是不(既然不选第i+j个数,相当于不存在呗)~~如果选了呢,就是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]|)

这样我们终于可以写出代码了T^T

/** 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]);
        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;
}

好了,这回AC了。

但是看了别人的博客,可以用到滚动数组【啊喂!!我就是为了学一下滚动数组才搜到这道题的,结果根本不用啊!】。

滚动数组很神奇啊,因为对于每一个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……

继续努力~

时间: 2024-10-13 12:21:59

HDU 3392 Pie(DP+滚动数组)的相关文章

HDU 3392 Pie(滚动数组优化)

Problem Description A lot of boys and girls come to our company to pie friends. After we get their information, we need give each of them an advice for help. We know everyone's height, and we believe that the less difference of a girl and a boy has,

HDU - 6578 Blank DP + 滚动数组

HDU - 6578 Blank 题意 给你\(\{0,1,2, 3\}\)四个数,分别填入长度为\(n\)的数列中,有\(m\)个限制条件,\(l_{i}, r_{i}, x_{i}\)表示在\([l_{i}, r_{i}]\)区间内,只能有\(x_{i}\)个不同的数.问一共有多少总方案. 思路 首先, 我们可以用\(dp[i][j][k][w]\)来表示方案数,\(i, j, k, w\)不是特指对应某个数字,而是四种不同的数字从小到大最后出现的位置\((i < j < k <w)

HDU 1024 Max Sum Plus Plus --- dp+滚动数组

HDU 1024 题目大意:给定m和n以及n个数,求n个数的m个连续子系列的最大值,要求子序列不想交. 解题思路:<1>动态规划,定义状态dp[i][j]表示序列前j个数的i段子序列的值,其中第i个子序列包括a[j], 则max(dp[m][k]),m<=k<=n 即为所求的结果 <2>初始状态: dp[i][0] = 0, dp[0][j] = 0; <3>状态转移: 决策:a[j]自己成为一个子段,还是接在前面一个子段的后面 方程: a[j]直接接在前面

HDU 5617 Jam&#39;s maze dp+滚动数组

题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5617 bc(中文):http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=666&pid=1003 题解: 设dp[x1][x2][i]表示第i步时,从(1,1)点走到了(x1,y1),(n,n)点走到了(x2,y2)点的合法的总数. 1 #include<iostream> 2 #include

[ACM] HDU 4576 Robot (概率DP,滚动数组)

Robot Problem Description Michael has a telecontrol robot. One day he put the robot on a loop with n cells. The cells are numbered from 1 to n clockwise. At first the robot is in cell 1. Then Michael uses a remote control to send m commands to the ro

HDU - 2294 Pendant (DP滚动数组降维+矩阵快速幂)

Description On Saint Valentine's Day, Alex imagined to present a special pendant to his girl friend made by K kind of pearls. The pendant is actually a string of pearls, and its length is defined as the number of pearls in it. As is known to all, Ale

HDU 5119 Happy Matt Friends (背包DP + 滚动数组)

题目链接:HDU 5119 Problem Description Matt has N friends. They are playing a game together. Each of Matt's friends has a magic number. In the game, Matt selects some (could be zero) of his friends. If the xor (exclusive-or) sum of the selected friends'ma

poj3624 01背包入门 dp+滚动数组

poj3624 01背包 dp+滚动数组 Charm Bracelet Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 25458   Accepted: 11455 Description Bessie has gone to the mall's jewelry store and spies a charm bracelet. Of course, she'd like to fill it with the bes

POJ3071-Football(概率DP+滚动数组)

Football Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2769   Accepted: 1413 Description Consider a single-elimination football tournament involving 2n teams, denoted 1, 2, -, 2n. In each round of the tournament, all teams still in the