栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

关于一道01背包问题的·拓展题的思考

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

关于一道01背包问题的·拓展题的思考

[USACO03FALL]Cow Exhibition G 题目背景 题目描述

奶牛想证明它们是聪明而风趣的。为此,贝西筹备了一个奶牛博览会,她已经对 N N N 头奶牛进行了面试,确定了每头奶牛的智商和情商。

贝西有权选择让哪些奶牛参加展览。由于负的智商或情商会造成负面效果,所以贝西不希望出展奶牛的智商之和小于零,或情商之和小于零。满足这两个条件下,她希望出展奶牛的智商与情商之和越大越好,请帮助贝西求出这个最大值。

输入格式

第一行:单个整数 N N N, 1 ≤ N ≤ 400 1 le N le 400 1≤N≤400。

第二行到第 N + 1 N+1 N+1 行:第 i + 1 i+1 i+1 行有两个整数: S i S_i Si​ 和 F i F_i Fi​,表示第 i i i 头奶牛的智商和情商,− 1000 ≤ S i ; F i ≤ 1000 1000 le S_i;F_i le 1000 1000≤Si​;Fi​≤1000。

输出格式

输出单个整数:表示情商与智商和的最大值。贝西可以不让任何奶牛参加展览,如果这样做是最好的,输出 0 0 0。

样例 #1 样例输入 #1
5
-5 7
8 -6
6 -3
2 1
-8 -5
样例输出 #1
8
提示

选择第一头,第三头,第四头奶牛,智商和为−5+6+2 = 3,情商和为7−3+1 = 5。再加

入第二号奶牛可使总和提升到10,不过由于情商和变成负的了,所以是不允许的

这道题是01背包问题的一个拓展,挺难想到的,将智商当作体积,情商当作价值,
因为智商有负值,根据数据可算出智商之和: -400*1000 <= sum <= 400 * 1000,.
所以可以将智商加上偏移量400*1000,这样作为数组下标就不会越界了

画重点: 这题话要保证dp[j]是恰好智商和为j-M,如何保证呢?这就是下面代码中的先初始化所有值为-0x3f3f3f3f,这个数值的两倍不会溢出,然后初始化f[M]=0,这样在状态转移时我们最终取得max中的最大值是那些从0转移过去的状态,也就是恰好经过多次迭代dp[j] = max(dp[j], dp[j - s[i]] + f[i]);最终的最大值来源是从dp[M]也就是智商和为0转移过去的,这样就保证了我们最后的结果dp[j]一定是恰好智商和为j-M
思路参考了: 背包问题复习题单讲解
代码如下:

#include 
#include 
#include 
#include 

using namespace std;

const int N = 1e6 + 10, M = 400 * 1000;

int dp[N], n, s[N], f[N];

int main()
{
    cin >> n;
    for(int i = 0; i < n; i ++)
        cin >> s[i] >> f[i];
    memset(dp, -0x3f, sizeof dp);//因为情商有负值,取max,要初始化负无穷
    dp[M] = 0;//这两行保证了dp[j]是恰好智商和为j-M
    for(int i = 0; i < n; i ++){
   		//对01背包进行了拓展,因为j - s[i]可能是大于j也可能是小于j
   		//一维化处理了,实际是dp[i][j],从前i个中在智商只有j-M时选的最大情商
   		//所以如果j - s[i]大于j就要正序遍历更新,因为用的是上一层后面的
   		//如果j - s[i]小于j就要逆序遍历更新,因为用的是上一层前面的
        if(s[i] >= 0)
            for(int j = 2 * M; j >= s[i]; j --)
                dp[j] = max(dp[j], dp[j - s[i]] + f[i]);
        else
            for(int j = 0; j <= s[i] + 2 * M; j ++)
                dp[j] = max(dp[j], dp[j - s[i]] + f[i]);
    }
    int  res = 0;
    for(int i = M; i <= 2 * M; i ++)
        if(dp[i] > 0)
            res = max(res, dp[i] + i - M);
    cout << res << endl;
    return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/938026.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号