奶牛会展

题目背景

奶牛想证明它们是聪明而风趣的。为此,贝西筹备了一个奶牛博览会,她已经对N 头奶牛进行

了面试,确定了每头奶牛的智商和情商。

题目描述

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

输入输出格式

输入格式:

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

• 第二行到第N + 1 行:第i + 1 行有两个整数:Si 和Fi,表示第i 头奶牛的智商和情商,−1000 ≤ Si; Fi ≤ 1000

输出格式:

输出格式

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

输入输出样例

输入样例#1:

5
-5 7
8 -6
6 -3
2 1
-8 -5

输出样例#1:

8

说明

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

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

解析:由于这是每个奶牛装或不装,很明显这是一个01背包

状态:dp[i][j]=x表示考虑到1-i头奶牛,智商和为j的最大情商和为x

答案:max{dp[n][j](0<=j<=400000)}

转移:dp[i][j]=max(dp[i-1][j-IQ[i]]+EQ[i],dp[i-1][j])

初值:memset(dp,-999999,sizeof(dp))

dp[i][0]=1(0<=i<=n)

但是由于j有可能为负数,所以要将dp数组整体平移

由-400000-400000 变成0-800000

所以代码是这个样子的:

#include<bits/stdc++.h>
using namespace std;
int IQ[401],EQ[401];
int dp[401][800001];
int ans;
int main()
{
    	int n;
    	scanf("%d",&n);
   	for(int i=1;i<=n;i++)
   	{
        		scanf("%d%d",&IQ[i],&EQ[i]);
    	}
    	memset(dp,-999999,sizeof(dp));
    	for(int i=0;i<=n;i++) dp[i][400000]=0;
    	for(int i=1;i<=n;i++)
    	{
        		for(int j=1;j<=800000;j++)
        		{
            		if(j>IQ[i])
            		{
            			dp[i][j]=max(dp[i-1][j],dp[i-1][j-IQ[i]]+EQ[i]);
            		}
            		else
            		{
                			dp[i][j]=dp[i-1][j];
            		}
        		}
        		for(int j=1;j<=800000;j++)
        		{
            		dp[i-1][j]=dp[i][j];
        		}
    	}
    	for(int i=400000;i<=800000;i++)
    	{
        		if(dp[n][i]>=0) ans=max(ans,dp[n][i]+i-400000);
    	}
    	cout<<ans;
    	return 0;
}

  

但是你只要稍微测试一下就知道,这个代码会MLE。。。

下面来介绍一下我的解决方法:滚动数组!!!

这是指在第i项只与第i-1项有关系的一种dp优化方法,这可以将第i-2项之前省略,能节省空间。

数组滚动后的代码如下:

#include<bits/stdc++.h>
using namespace std;
int IQ[401],EQ[401];
int dp[3][800001];
int ans;
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&IQ[i],&EQ[i]);
    }
    memset(dp,-999999,sizeof(dp));
    dp[1][400000]=0;
    dp[2][400000]=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=800000;j++)
        {
            if(j>IQ[i])
            {
                dp[2][j]=max(dp[1][j],dp[1][j-IQ[i]]+EQ[i]);
            }
            else
            {
                dp[2][j]=dp[1][j];
            }
        }
        for(int j=1;j<=800000;j++)
        {
            dp[1][j]=dp[2][j];
        }
    }
    for(int i=400000;i<=800000;i++)
    {
        if(dp[1][i]>=0) ans=max(ans,dp[1][i]+i-400000);
    }
    cout<<ans;
    return 0;
}

  

完美解决

原文地址:https://www.cnblogs.com/chen-1/p/10886635.html

时间: 2024-10-29 20:30:17

奶牛会展的相关文章

洛谷P2340 奶牛会展

洛谷P2340 奶牛会展用下标表示智商,值表示情商 1 #include <bits/stdc++.h> 2 #define For(i,j,k) for(int i=j;i<=k;i++) 3 using namespace std ; 4 5 const int N = 411 ; 6 int n,m ; 7 int a[N],b[N],f[800011] ; 8 9 inline int read() 10 { 11 int x = 0 , f = 1 ; 12 char ch =

[USACO]奶牛会展(背包)

[USACO]奶牛会展 题目背景 奶牛想证明它们是聪明而风趣的.为此,贝西筹备了一个奶牛博览会,她已经对N 头奶牛进行 了面试,确定了每头奶牛的智商和情商. 题目描述 贝西有权选择让哪些奶牛参加展览.由于负的智商或情商会造成负面效果,所以贝西不希望出展奶牛的智商之和小于零,或情商之和小于零.满足这两个条件下,她希望出展奶牛的智商与情商之和越大越好,请帮助贝西求出这个最大值. 输入输出格式 输入格式: ? 第一行:单个整数N,1 ≤ N ≤ 400 ? 第二行到第N + 1 行:第i + 1 行有

【Luogu】P2340奶牛会展

题目链接 突发奇想可以用f[i]表示智商和为i的时候情商最大是多少.这样就变成了一个背包问题. 最后更新答案的时候从0到最大背包容量遍历,最后答案是最大的i+f[i]; 但是虽然答案只能从0到m里选,转移过程中是不能丢掉负数体积的.这是因为人家题目只说了要最后的智商和不能小于零,情商和不能小于零,没说中间不可以. 代码如下. #include<cstdio> #include<cctype> #include<cstring> #include<algorithm

题解 P2340 【奶牛会展】

此题搜索可以过!!! 看到此题,第一想法,是01背包,然而,作为一个蒟蒻,我怎么会打正解呢?,于是就开始打dfs! 想要完成此题,普通的搜索肯定是过不了的(不然要dp干嘛),所以,我们要考虑 剪枝 比较容易的,我们可以轻松想出来剪枝: (不吐槽名字我们还是好朋友...) 1.用数组guji[i]表示搜索到i时,不考虑智商,情商必须大于零的限制,之后能获得的最大智,情商之和.如果当前搜索到的智,情商之和加上guji[i]任然小于等于已经搜出来的ans,那么,当前的状态一定不是最优的(这属于最优性优

【题解】luogu p2340 奶牛会展

总结:1.智商从哪开始循环没想到. 2.将智商的正负分开讨论.负智商要用顺序,保证不会使一头牛多用. 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXN = 800005; 4 int dp[MAXN], n, iq[405], eq[405], maxx = -2000000; 5 int main() 6 { 7 memset(dp, -0x3f, sizeof(dp)); 8 dp[400000] = 0;

饥饿的奶牛(洛谷 1868)

题目描述 有一条奶牛冲出了围栏,来到了一处圣地(对于奶牛来说),上面用牛语写着一段文字. 现用汉语翻译为: 有N个区间,每个区间x,y表示提供的x~y共y-x+1堆优质牧草.你可以选择任意区间但不能有重复的部分. 对于奶牛来说,自然是吃的越多越好,然而奶牛智商有限,现在请你帮助他. 输入输出格式 输入格式: 第一行,N,如题 接下来N行,每行一个数x,y,如题 输出格式: 一个数,最多的区间数 输入输出样例 输入样例#1: 3 1 3 7 8 3 4 输出样例#1: 5 说明 1<=n<=15

AC日记——[USACO5.4]奶牛的电信Telecowmunication 洛谷 P1345

[USACO5.4]奶牛的电信Telecowmunication 思路: 水题: 代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 205 #define maxm 20005 #define INF 0x3f3f3f3f int head[maxn],cnt=1,n,m,E[m

洛谷 P2742 [USACO5.1]圈奶牛Fencing the Cows

题目描述 农夫约翰想要建造一个围栏用来围住他的奶牛,可是他资金匮乏.他建造的围栏必须包括他的奶牛喜欢吃草的所有地点.对于给出的这些地点的坐标,计算最短的能够围住这些点的围栏的长度. 输入输出格式 输入格式: 输入数据的第一行包括一个整数 N.N(0 <= N <= 10,000)表示农夫约翰想要围住的放牧点的数目.接下来 N 行,每行由两个实数组成,Xi 和 Yi,对应平面上的放牧点坐标(-1,000,000 <= Xi,Yi <= 1,000,000).数字用小数表示. 输出格式

那么大奶牛之神

题目描述 那么大奶牛之神把一个神秘数字通过信使传递给了奶牛们,但由于信件上出现了偏差,一个数字变成了两个数字,现在你需要通过这两个数字还原出大么大奶牛之神给的神秘数字.需要用第二个数字通过加(+),减(-),乘(*),除(/),次幂(^),阶乘(!),开平方(√)这几个符号凑出第一个数字.使用第二个数字的次数最少的时候,那么使用次数就是神秘数字. 例如第一个数字是300,第二个数字是7,那么7用得最少是6次,所以神秘数字是6.具体方法如图用了6个7.虽然最优解的算式不是唯一的,但是并不妨碍得到最