hdoj 3732 Ahui Writes Word (多重背包)

简介: 来看题目吧,可能有100000个单词,然后只有1000ms,但看包的大小,有10000,这样只能允许nlog(n)的算法,还有,每个单词的价值和花费都很小(不大于十),如果不考虑单词的不同,只考虑价值和花费只有最多100种东西,但如果把这些按多重背包的方法来计算依旧会超时,很容易想到和之前01背包的时间复杂度是一样的。

之前在做背包的题目时看到了这道题,一看,大喜,这不是裸裸的01背包吗!!  然后华丽丽的超时,相信很多人也和我一样没有考虑到数据量的大小。


     时隔多日,回过头来看这道题,依旧毫无头绪。。。。不过相比之前,我看到了更多细节。


     来看题目吧,可能有100000个单词,然后只有1000ms,但看包的大小,有10000,这样只能允许nlog(n)的算法,还有,每个单词的价值和花费都很小(不大于十),如果不考虑单词的不同,只考虑价值和花费只有最多100种东西,但如果把这些按多重背包的方法来计算依旧会超时,很容易想到和之前01背包的时间复杂度是一样的。


     还记得多重背包可以转换为01背包吗??我们不妨把这些物品进行打包,把每种物品分别1个、2个、4个…………(2^k)个进行打包,如果不足2^k个则单独打包,然后把每一包看做一件物品,继续使用01背包的方法进行计算,这样我们就把原来O(nc)的时间复杂度降到了O(clogn)。

//hdoj 3732
//2013-08-10-16.53
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int dp[10005];
int vc[11][11];
int w[10005];
int v[10005];
int main()
{
    int n, c;
    char s[100];
    while (scanf("%d %d", &n, &c) != EOF)
    {
        int a, b;
        memset(dp, 0, sizeof(dp));
        memset(vc, 0 ,sizeof(vc));
        for (int i = 1; i <= n; i++)
        {
            scanf("%s %d %d", &s, &a, &b);
            vc[a][b]++;
        }
        int cnt = 1;
        for (int i = 1; i <= 10; i++)
        {
            for (int j = 1; j <= 10; j++)
            {
                if (vc[i][j])
                {
                    int tmp = 1;
                    while (vc[i][j] > tmp)
                    {
                        w[cnt] = tmp*j;
                        v[cnt] = tmp*i;
                        vc[i][j] -= tmp;
                        cnt++;
                        tmp <<= 1;
                    }
                    w[cnt] = j*vc[i][j];
                    v[cnt] = i*vc[i][j];
                    cnt++;
                }
            }
        }
        for (int i = 1; i < cnt; i++)
        {
            for (int j = c; j >= w[i]; j--)
                dp[j] = max(dp[j], dp[j-w[i]] + v[i]);
        }
        printf("%d\n", dp[c]);
    }
    return 0;
}
目录
相关文章
|
10月前
|
算法
The kth great number(小根堆思想,模板题)
The kth great number(小根堆思想,模板题)
30 0
The kth great number(小根堆思想,模板题)
|
存储 Python
LeetCode 315. Count of Smaller Numbers After Self
给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。
78 0
LeetCode 315. Count of Smaller Numbers After Self
|
人工智能 BI
AtCoder Beginner Contest 216 F - Max Sum Counting (降维 背包dp)
AtCoder Beginner Contest 216 F - Max Sum Counting (降维 背包dp)
108 0
HDOJ 1016 Prime Ring Problem素数环【深搜】
HDOJ 1016 Prime Ring Problem素数环【深搜】
98 0
HDOJ 1016 Prime Ring Problem素数环【深搜】
HDOJ 1391 Number Steps(打表DP)
HDOJ 1391 Number Steps(打表DP)
108 0
HDOJ 1391 Number Steps(打表DP)
HDOJ 1081(ZOJ 1074) To The Max(动态规划)
HDOJ 1081(ZOJ 1074) To The Max(动态规划)
71 0
HDOJ 1081(ZOJ 1074) To The Max(动态规划)
Optimal Coin Change(完全背包计数)
题目描述 In a 10-dollar shop, everything is worthy 10 dollars or less. In order to serve customers more effectively at the cashier, change needs to be provided in the minimum number of coins. In this problem, you are going to provide a given value of the change in different coins.
77 0
|
C语言
HDOJ 1016 Prime Ring Problem素数环【深搜2】
HDOJ 1016 Prime Ring Problem素数环【深搜】
84 0
HDOJ(HDU) 2136 Largest prime factor(素数筛选)
HDOJ(HDU) 2136 Largest prime factor(素数筛选)
96 0