Luogu P2297 刷图 DP

题目背景

loidc,LOI中的传说级哲♂学家,曾经创造一天内入坑maxlongint个弃坑0x7fffffff个的神奇纪录。目前,loidc最喜欢的游戏就是地下城与勇♂士。

题目描述

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{}表示求和

LuoguP2340 奶牛会展 双倍经验爽!!

提交地址 : https://www.luogu.org/problemnew/show/P2297#sub

      and https://www.luogu.org/problemnew/show/P2340#sub

 分析:

  裸裸的01背包吗。

 把属性a当做体积, 属性b当做价值;

 妥妥的ok;

 但有个小问题,数组并不能存负值;

 所以要平移数组,最后就是裸背包;

 然后枚举移动的位数,判断b属性大于零,然后 取max;

 代码:

// By zZhBr
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

int n;

int m;
int a[110], b[110];

int dp[110001];

int ans;

int main()
{
    cin >> n;
    
    for(register int i = 1 ; i <= n ; i ++)
    {
        scanf("%d%d", &a[i], &b[i]);
        m += a[i] > 0 ? a[i] : 0;
    }
    
    memset(dp, 0xcf, sizeof dp);
    
    m *= 2;
    dp[m/2] = 0;
    
    for(register int i = 1 ; i <= n ; i ++)
    {
        if(a[i] > 0)
        {
            for(register int j = m ; j >= a[i] ; j --)
            {
                dp[j] = max(dp[j], dp[j-a[i]] + b[i]);
            }
        }
        else 
        {
            for(register int j = 0 ; j <= m - a[i] ; j ++)
            {
                dp[j] = max(dp[j], dp[j-a[i]] + b[i]);
            }
        }
    }
    
    int k = m / 2;
    
    for(register int i = 1 ; i <= k ; i ++)
    {
        if(dp[i+k] >= 0)
        {
            ans = max(ans, i + dp[i+k]);
        }
    }
    
    printf("%d\n", ans);
    return 0;
}
zZhBr
原文地址:https://www.cnblogs.com/BriMon/p/8945929.html