习题:刷图(01背包)

洛谷2297

题目描述

Loidc是一个勤奋的孩子。 他每天都会勤奋的搬砖刷疲劳,每天都会期待着各种BOSS给他爆点什么神奇的东西(例如魔剑..),但是每次刷远古总会坑到连门票钱也赚不回来。 最近loidc新技能get√ 他每天都会朗诵一遍线段树,将自己升级为”Deep Dark Fantasy”模式(其实是每天去给腾讯爹送钱)下才去搬砖,所以他人品次次爆发,每次刷图后腾讯都会象征性给他爆点好东西。 今天他又来刷一个叫做“痛苦之村列瑟芬”的图,每次刷完图后都会有N个掉落物。但是loidc很健忘,他每次都会忘清空背包,所以不一定是所有东西都能带回去。 i个物品有两个属性A_i和B_i,现在loidc需要在其中选取若干个物品,使得sum{A_i + B_i}最大,同时sum{A_i},sum{B_i}均非负。但是由于loidc太弱,所以这个工作交给了你。

输入输出格式

输入格式:
第一行,一个整数,表示掉落物个数N。 接下来N行,每行两个整数,表示A_i和B_i。

输出格式:
一个整数,表示最大的sum{A_i + B_i}。

输入输出样例

输入样例#1:
5
-5 7
8 -6
6 -3
2 1
-8 -5
输出样例#1:
8
说明

N <= 100 , |A_i| <= 1000 , |B_i| <= 1000

sum{}表示求和

分析:

用f[i,j]表示sum(ai)=i时sum(bi)的最大值。

这样就变成01背包了

但注意因为有负数,要分情况转移。

代码:

program hehe;
var
  a,b:array[0..100]of longint;
  f:array[-100000..100000]of longint;
  n,i,m,j,ans,v:longint;
function max(x,y:longint):longint;
begin
  if x>y then max:=x else max:=y;
end;
begin
  readln(n);
  for i:=1 to n do
  begin readln(a[i],b[i]); if a[i]<0 then v:=v+a[i] else m:=m+a[i]; end;
  f[0]:=0; for i:=1 to m do f[i]:=-maxlongint div 3;
  for i:=1 to n do
  if a[i]>=0 then begin
   for j:=m downto v+a[i] do
    f[j]:=max(f[j],f[j-a[i]]+b[i]);
  end
   else begin
    for j:=v to m+a[i] do
    f[j]:=max(f[j],f[j-a[i]]+b[i]);
   end;
  for i:=0 to m do
   if f[i]>=0 then begin ans:=max(f[i]+i,ans); end;
  writeln(ans);
end.

时间: 2024-10-11 02:05:24

习题:刷图(01背包)的相关文章

hihoCoder1055.刷油漆——树形Dp+01背包

http://hihocoder.com/problemset/problem/1055 一棵有根树,包含根节点1,选择M个连续的节点,使得权值最大 dp[u][j] 表示以i为根的子树中,选择包含根节点的j个连续节点所能获得的最大权值 枚举子节点选择的个数,儿子节点选择的个数,当做01背包 #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include

hihoCoder#1055 : 刷油漆 (树形DP+01背包)

题目大意:给一棵带点权的树,现在要从根节点开始选出m个连通的节点,使总权值最大. 题目分析:定义状态dp(u,m)表示在以u为根的子树从根节点开始选出m个点连通的最大总权值,则dp(u,m)=max(dp(u,m),dp(u,m-k)+dp(son,k)),其中0<=k<m.这是01背包,k应该从大往小枚举. 代码如下: # include<iostream> # include<cstdio> # include<cmath> # include<v

01背包

这里就只放自己刷的题目了,毕竟是弱弱哒 HDU2546:饭卡 1 #include <algorithm> 2 #include <cstdio> 3 4 using namespace std; 5 6 int main() 7 { 8 int n,m; 9 while (~scanf("%d", &n), n) 10 { 11 int f[2013] = {0}, menu[2013] = {0}; 12 for (int i = 1; i <

HDU 1864 01背包、

这题题意有点坑阿.感觉特别模糊. 我开始有一点没理解清楚.就是报销的话是整张整张支票报销的.也是我傻逼了 没一点常识 还有一点就是说单张支票总额不超过1000,每张支票中单类总额不超过600,我开始以为是题目数据会这样给. 没想到还要自己判断 并且不符合条件的支票要直接舍去.- -.只能怪自己题目做少了.   没事还是好好刷题.   纵使别人放弃 我也不允许自己放弃 这题的输入数据全部都是2位小数,可以直接化为整数处理 然后就是裸的01背包了 1 #include<iostream> 2 #i

01背包水题篇之 HDU2955——Robberies

原来是想dp[i],表示不被抓概率为i所能抢到的最大钱(概率1-100) 后来看了别人的博客是dp[i]表示抢了i钱最大的不被抓概率,嗯~,弱菜水题都刷不动. 那么状态转移方程就是 dp[i]=max(dp[i],dp[i-money]*p),初始化dp(0~maxn)为0,dp[0]=1(1毛钱都没抢你抓个毛线啊,哥是良民~) 又是贴代码环节~ <span style="font-size:18px;">#include<iostream> #include&

01背包水题篇之HDU3466——Proud Merchants

这是个好题,菜鸟刚学dp,这题把我以前的想法全都给完完全全的颠覆了.其实是自己没了解无后效性的概念. 然后我去开开心心滴跑去问队长:"队长,队长,怎么理解动归的无后效性啊???" 学长很深沉滴对我说:"做多了就会了" "噢噢"(好吧) 然后学长又补了句:"能构成有向无环图的都能用DP搞." 我心里想:"队长就知道搞妹~~~." 默默去翻小白书看看DAG去了. 为了搞清楚这题怎么写,操了度娘千百遍,还是没搞定

HDU 2546 饭卡( 变形01背包)两种思路

中文题:给你n个菜的价格,问m元最少剩下多少.一个条件是:若大于等于5元可以任意刷一次.卡上金额一定要大于5才可以 第一种: dp[j] 用前n-1个物品能否构成j元 变形01背包.若整个菜的价值和都小于m则m-sum; 否则,按升序排序,易证最后用5购买的菜必然是最后一个.先将背包前n-1个放入,看能放入的数据是多少,然后判断m-5后能出现哪些,利用规则替换n物品 #include<iostream> #include<cmath> #include<cstdio>

01背包//简直要被这道题玩死(掀桌)

先上链接: 表格什么的最清楚了:http://blog.csdn.net/mu399/article/details/7722810 dd大大的背包九讲: —————————————————— 01背包的状态转换方程 f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ),  f[i-1,j] } f[i,j]表示在前i件物品中选择若干件放在承重为 j 的背包中,可以取得的最大价值. Pi表示第i件物品的价值. 决策:为了背包中物品总价值最大化,第 i件物品应该放入背包中

【转】背包问题——“01背包”详解及实现(包含背包中具体物品的求解)

01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为C1,C2,…,Cn,与之相对应的价值为W1,W2,…,Wn.求解将那些物品装入背包可使总价值最大. 动态规划(DP): 1) 子问题定义:F[i][j]表示前i件物品中选取若干件物品放入剩余空间为j的背包中所能得到的最大价值. 2) 根据第i件物品放或不放进行决策                         (1-1) 其中F[i-1][j]表示前i-1件物品中选取若干件物品放入剩余空间为j的背包中所能得到的最大价值: 而