hihocoder笔记

原创 2016年08月29日 22:31:12

hihocoer系列

p1364 奖券兑换

题目:

描述
小Hi在游乐园中获得了M张奖券,这些奖券可以用来兑换奖品。
可供兑换的奖品一共有N件。第i件奖品需要Wi张奖券才能兑换到,其
价值是Pi。
小Hi使用不超过M张奖券所能兑换到的最大奖品总价值是多少?

输入
第一行两个整数N,M。  
接下来N行,每行两个整数Wi,Pi。  
对于 50%的数据: 1≤N,M≤1000  
对于 100%的数据: 1≤N,M≤10e5,1≤Pi,Wi≤10。  

输出
一行一个整数,表示最大的价值。

分析:

0-1背包问题,时间复杂度O(NM),空间复杂度O(NM)

for(int i = 0;i <= M;i ++) 
    dp[0][i] = 0;
for(int i = 1;i <= N;i ++)
    for(int j = 0;j <= M;j ++)
        dp[i][j] = max(dp[i-1][j], dp[i-1][j-W[i]]+P[i]);

0-1背包问题,空间复杂度优化O(M)

for(int i = 0;i <= M;i ++)
    dp[i] = 0;
for(int i = 1;i <= N;i ++)
    for(int j = M;j >= 0;j --)
        dp[j] = max(dp[j], dp[j-W[i]]+P[i]);

由于1≤Pi,Wi≤10这个条件,此题0-1背包问题可以转换为多重背包问题
多重背包问题可以采用二进制优化。
定义多重背包问题为:
N件物品,第i件物品重量为Wi,价值为Pi,数量为Ci。求容量为M的背包可取物品的最大价值。
O(NMK)(K为物品的最大数量)的写法

for(int i = 0;i <= M;i ++)
    dp[0][i] = 0;
for(int i = 1;i <= N;i ++)
    for(int j = 0;j <= M;j ++)
        for(int k = 0;k <= C[i];k ++)
            dp[i][j] = max(dp[i][j], dp[i-1][j-W[i]*k]+P[i]*i);

二进制优化:
设t = logCi ,数量Ci可分解为20+21+...+2t+(Ci2021...2t)
第i件物品应该取走的数目可表示为b020+b121+...+bt2t+b(t+1)a(Ci2021...2t)
其中b为二进制变量
因此第i件物品的最佳取法变成了b的最佳取值,这又变成了0-1背包问题
转换过程具体代码如下

int count = 0;
int bitP[maxm];
int bitW[maxm];

for(int i = 1;i <= N;i ++){
    int k;
    for(k = 1;(k<<1) <= C[i];k <<= 1){
        bitP[count] = P[i]*k;
        bitW[count] = W[i]*k;
        count ++;
    }
    bitP[count] = P[i]*(C[i]-k+1);
    bitW[count] = W[i]*(C[i]-k+1);
    count ++; 
}   

代码

#include <iostream>
#include <stdio.h>
using namespace std;

#define maxm(a, b) ((a)>(b)?(a):(b))

#define MAXW 10
#define MAXP 10
#define MAXCOUNT 2000
#define MAXM 100000

int ticket[MAXW][MAXP];
int W[MAXCOUNT];
int P[MAXCOUNT];
int dp[MAXM + 1];

int n, m, count;

int main()
{
    cin>>n>>m;

    for(int i = 0;i < MAXW;i ++)
        for(int j = 0;j < MAXP;j ++)
            ticket[i][j] = 0;

    int w, p;
    for(int i = 0;i < n;i ++){
        scanf("%d %d", &w, &p);
        ticket[w-1][p-1] ++;
    }

    int k, count = 0;
    for(int i = 0;i < MAXW;i ++){
        for(int j = 0;j < MAXP;j ++){
            for(k = 1;(k<<1) <= ticket[i][j]; k <<= 1){
                W[count] = (i+1)*k;
                P[count] = (j+1)*k;
                count ++;
            }
            W[count] = (i+1)*(ticket[i][j] - k + 1);
            P[count] = (j+1)*(ticket[i][j] - k + 1);
            count ++;
        }
    }

    for(int i = 0;i <= m;i ++)
        dp[i] = 0;

    for(int i = 0;i < count;i ++){
        for(int j = m;j >= 0;j --){
            if(j >= W[i]){
                dp[j] = maxm(dp[j], dp[j-W[i]] + P[i]);
            }
        }
    }

    cout<<dp[m]<<endl;
    return 0;
}

hihoCoder#1032_最长回文子串

求最长回文子串的算法比较经典的是manacher算法,下面写写自己的理解。 (文中用到的图片来自这里,博主写的很好,由于为了图片和代码一致,我稍微p了一下图片。) 首先,说明一下用到的数组和其他参...
  • sinat_30071459
  • sinat_30071459
  • 2016年04月02日 19:37
  • 1483

ACM解题总结——HihoCoder1199 (微软笔试题)

题目来源:     HihoCoder1199  题目要求:     There is a tower defense game with n levels(missions). The n le...
  • octopusflying
  • octopusflying
  • 2016年08月03日 21:25
  • 1310

hihocoder #1033 交错和问题的思考

题目要求如下: 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, …, an - 1,定义...
  • u011467044
  • u011467044
  • 2016年11月08日 22:26
  • 443

hihoCoder - 1089 - 最短路径·二:Floyd算法 (floyd算法!!)

#1089 : 最短路径·二:Floyd算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 万圣节的中午,小Hi和小H...
  • u014355480
  • u014355480
  • 2015年01月01日 23:15
  • 757

交错和 (hihocoder)

求L到R之间的交错和为K的
  • jiangjiashi
  • jiangjiashi
  • 2014年10月08日 16:23
  • 3069

微软2016校园招聘4月在线笔试 hihocoder 1288 Font Size (模拟)

微软2016校园招聘4月在线笔试 hihocoder 1288 Font Size (模拟)
  • Tc_To_Top
  • Tc_To_Top
  • 2016年04月07日 14:20
  • 828

hihoCoder 1166 交换代数 (高斯消元,概率)

题意: 给出区间[1,n]的状态,有0、1.现在每次可以选择任意区间取翻转,问全部翻转成0的次数期望。总共有n(n+1)/2个区间。 题解: 这个CLJ链接将的很清楚了。 那么根据高斯消元列方...
  • My_ACM_Dream
  • My_ACM_Dream
  • 2015年05月19日 23:49
  • 673

HihoCoder - 1457 后缀自动机四·重复旋律7 后缀自动机+拓扑排序+递推、BFS

题意:所有字符串的不同子串的“和”(也就是把串看成数字,在十进制下的求和,允许有前导0)。 后缀自动机+拓扑排序+递推、BFS 首先如果只是一个字符串,则转移的时候,st[i] == v节点会转移到u...
  • ProLightsfxjh
  • ProLightsfxjh
  • 2017年04月22日 19:02
  • 745

Tarjan(无向图双联通分量)——hihoCoder 1184

题目链接: https://hihocoder.com/problemset/problem/1184 分析: 给出一个N个点,M条边的无向图,求出其最小双联通分量的个数,每个双联通分量用其中点的...
  • FeBr2
  • FeBr2
  • 2016年10月15日 21:45
  • 288

hihocoder[Offer收割]编程练习赛3及参考

hihocoder[Offer收割]编程练习赛3及参考
  • u010913001
  • u010913001
  • 2016年08月04日 16:18
  • 577
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:hihocoder笔记
举报原因:
原因补充:

(最多只允许输入30个字)