poj 2184 0---1背包的变形

这题是0--1背包的变形,对理解0--1背包有很大的帮组

题意:要选一些牛去参见展览,每个牛有幽默、智慧两个选择标准,要求选的这些牛使得幽默和智慧的总和最大且幽默和智慧的每个总和都必须是大于等于0;

刚看的这个题目是时候,知道是一个0--1背包的的题目,但就是不知道怎么来写出状态转移方程,因为题中的两个变量都是有负值的。

看了大牛的解题报告才知道。

我们可以把幽默个变量看成是体积 , 智慧看成是价值。

我们可以把每个牛幽默的值 , 放在一个坐标上,让后整体往右移,使得最小值为 0 , 那么这时候就不存在负值了。

由题意我们可以知道,幽默的最小值为:100*(-1000) , 也就是 -100000

那么我们就使每个幽默都 + 100000 , 那么这个体积(幽默)就不存在负值了。

但是当我们进行状态转移时 , 要分两种情况 :

1、体积(幽默) >= 0

这时就更普通的0---1背包一样 , 从大到小转移

dp[j] = max(dp[j] , dp[j-fi[i]]+ti[i]);

2、体积(幽默)< 0

这时在状态转移时 和 普通的 0---1背包正好相反 , 因为一个数减去一个负数 , 那么就会变成一个比原来那个数大的数 , 这时我们就要从小的到大进行状态转移。

dp[j] = max(dp[j] , dp[j-fi[i]]+ti[i]);

通过这个题,更进一步的理解了0---1背包

当体积存在负数时:

我们首先要把体积转变为非负数

然后在进行状态转移时 , 体积为负数的情况时 , 要反过来进行状态转移

代码:



//体积存在负数时
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

#define maxn 110
#define INF 200010
int fi[maxn] , ti[maxn];
int dp[INF];
int n;

int main()
{
    while(scanf("%d" , &n) != EOF)
    {
        int i , j;
        for(i = 1; i <= n; i++)
            scanf("%d %d" , &fi[i] , &ti[i]);
        for(i = 0; i <= 200000; i++)
            dp[i] = -INF*100;
        dp[100000] = 0;//这个位置表示0
        for(i = 1; i <= n; i++)
        {
            if(fi[i] >= 0)
            {
                for(j = 200000; j >= fi[i]; j--)
                    dp[j] = max(dp[j] , dp[j-fi[i]]+ti[i]);
            }
            else
            {
                for(j = fi[i]; j <= 200000+fi[i]; j++)
                    dp[j] = max(dp[j] , dp[j-fi[i]]+ti[i]);
            }
        }

        int ans = -INF*100;
        for(i = 100000; i <= 200000; i++)
            if(dp[i] >= 0)
                ans = max(ans , dp[i]+i-100000);
        cout<<ans<<endl;

    }
    return 0;
}

poj 2184 0---1背包的变形,布布扣,bubuko.com

时间: 2024-11-02 21:42:06

poj 2184 0---1背包的变形的相关文章

POJ 2184(01背包)(负体积)

http://poj.org/problem?id=2184 http://blog.csdn.net/liuqiyao_01/article/details/8753686 对于负体积问题,可以先定义一个“零点”shift,将dp[shift]设为0,其他都设为-INF. 然后负体积从0往maxn+cost更新,正体积从maxn往shift更新. 最后从shift到maxn中找最大值,shift以下的值不会被遍历到 #include <iostream> #include <strin

poj 2184 Cow Exhibition (变形的01背包)

链接:poj 2184 题意:给定n头牛,每头牛的的智商(si)和幽默感(fi)已知,求在保证智商(S)的和及幽默感(F)的和都为非负的情况下,智商和幽默感(S+T)的最大值 分析:题的本质即从n头牛中选出S>=0&&T>=0时,S+T的最大值 以智商最为容量,幽默感作为价值,因为每头牛只能选一次,就转化01背包了, dp[i]为智商为i时幽默感的最大值,则状态转移方程为 dp[j]=max(dp[j],dp[j-s[i]]+f[i]); 但是智商总和范围-100000~100

POJ 1636 Prison rearrangement DFS+0/1背包

题目链接: POJ 1636 Prison rearrangement Prison rearrangement Time Limit: 3000MS   Memory Limit: 10000K Total Submissions: 2194   Accepted: 984 Description In order to lower the risk of riots and escape attempts, the boards of two nearby prisons of equal

POJ 3628 Bookshelf 2 0/1背包和DFS两种解法

题目链接:POJ 3628 Bookshelf 2 Bookshelf 2 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7462   Accepted: 3436 Description Farmer John recently bought another bookshelf for the cow library, but the shelf is getting filled up quite quickly,

POJ 1745 【0/1 背包】

题目链接:http://poj.org/problem?id=1745 Divisibility Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13431   Accepted: 4774 Description Consider an arbitrary sequence of integers. One can place + or - operators between integers in the sequen

牛客网 TaoTao要吃鸡 ( 0/1背包变形 )

题意 : 题目链接 分析 :  如果没有 BUG (即 h == 0 的时候)就是一个普通的 0 / 1 背包 需要讨论一下 h != 0 的情况 此时有就相当于有物品是有特权的 而且背包装有特权的物品根据题目的要求是应当最后装的 也就是说特权物品装完之后背包将不再可装 所以特权物品肯定是只有一个的 数据量并不大,所以可以去枚举这个特权物品 那么如何知道在  没有装特权物品  之前的最佳选择方案? 答案就是用最小的可剩空间留给特权物品,然后其他空间去跑 0/1 背包 最小的可剩空间当然就是 h

POJ 2063 Investment 完全背包

题目链接:http://poj.org/problem?id=2063 今天果然是卡题的一天.白天被hdu那道01背包的变形卡到现在还没想通就不说了,然后晚上又被这道有个不大也不小的坑的完全背包卡了好久.这题主要是说让你选择不同的债券(每种债券的费用和年利率的属性),然后n年后使得本金最大,如果仅仅是问一年的话就是个裸完全背包的题了,不过它是n年,每年得到的总利息都会加入到本金中变为下一年的本金,知道了这个后就很好处理了,在这道题里每年变化的本金就是背包容量,然后债券那两个属性就是物品的费用(o

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

POJ 2392 Space Elevator 背包题解

多重背包,本题不需要二分优化.相对简单点.因为重复数十分小,小于10: 而增加一个限制每种材料的高度做法,如果使用逆向填表,那么只需要从这个高度往小递归填表就可以了. 还有就是注意要排序,以限制高度为标准从小到大排序,否则答案错误的. #include <stdio.h> #include <string.h> #include <algorithm> using std::sort; const int MAX_K = 401; const int MAX_H = 4