奶牛会展

题目背景

奶牛想证明它们是聪明而风趣的。为此,贝西筹备了一个奶牛博览会,她已经对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;
}

 

  

 

完美解决

 

posted @ 2019-05-18 18:19  CZD648  阅读(174)  评论(0编辑  收藏  举报
Live2D