zoukankan      html  css  js  c++  java
  • 奶牛会展

    题目背景

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

      

    完美解决

  • 相关阅读:
    JS中的prototype与面向对象
    机电传动控制第二周学习笔记
    第三周作业
    机电传动控制第四周作业
    第五周学习笔记
    机电传动控制第一周学习笔记
    个人项目图书管理系统登陆功能模拟
    GITHUB使用及入门总结
    我的github地址
    工作压力改变了我?
  • 原文地址:https://www.cnblogs.com/chen-1/p/10886635.html
Copyright © 2011-2022 走看看