zoukankan      html  css  js  c++  java
  • nowcoder 2020/6/20 J-小梁的背包

    小梁来到了伽勒尔地区并参加了联盟赛热身赛,比赛小岛上有n个精灵散落在岛上各处,她有一个大小为s的背包,每个精灵的战斗值为vi,体积为wi。
    请问在她临走之前背包内宝可梦的战斗力总和最多为多少,并输出其战斗值总和sum以及背包内的精灵数量ans。

    示例1
    输入

    1
    5 5
    1 3
    2 5
    1 2
    4 2
    6 1

    输出

    10 3

    背包问题,问了同学他说好像是多重背包?
    赛后搜得:背包问题详解

    这题恶心的地方是用dp求出最大的价值后还要让你计数,问放进去了多少个精灵球,卡了非常久。

    dp部分:
    我原本将这个计数的设为是cnt[i][j]=cnt[i-1][j];
    然后if判断是否放入,放入则cnt[i][j]++。这样是错误的,因为价值更新的话应该是前面那个容量的背包的次数再加一,而不是简单的++。
    应该改为

    cnt[i][j]=cnt[i-1][j];	
    
    //.....
    
    cnt[i][j]=cnt[i-1][j-g[i].w]+1;
    
    

    正解:

    	for(int i=1;i<=n;i++){
    		for(int j=0;j<=s;j++){
    			dp[i][j]=dp[i-1][j];
    			cnt[i][j]=cnt[i-1][j];	
    			if(j>=g[i].w){
    				if(dp[i-1][j-g[i].w]+g[i].v>dp[i-1][j]){
    					dp[i][j]=dp[i-1][j-g[i].w]+g[i].v;
    					cnt[i][j]=cnt[i-1][j-g[i].w]+1;
    				}				
    			}
    		}
    	}
    

    完整代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e4+5;
    
    struct gg{
    	int v,w;
    }g[N];
    int dp[N][N];
    int cnt[N][N];
    void solve()
    {
    	int n,s;
    	cin>>n>>s;
    	for(int i=1;i<=n;i++)cin>>g[i].w>>g[i].v;
    	for(int i=1;i<=n;i++){
    		for(int j=0;j<=s;j++){
    			dp[i][j]=dp[i-1][j];
    			cnt[i][j]=cnt[i-1][j];	
    			if(j>=g[i].w){
    				if(dp[i-1][j-g[i].w]+g[i].v>dp[i-1][j]){
    					dp[i][j]=dp[i-1][j-g[i].w]+g[i].v;
    					cnt[i][j]=cnt[i-1][j-g[i].w]+1;
    				}				
    			}
    		}
    	}
    	cout<<dp[n][s]<<" "<<cnt[n][s]<<endl;
    }
    
    int main()
    {
    	ios::sync_with_stdio(false);	
    	int t;
    	cin>>t;
    	while(t--)solve();
    	return 0;
    }
    

    dp仍然是我比较不熟练的部分,需要多做相关的题目。

    6/21 优化

    经同学提议优化了一下,将数组开成1维,节省了非常多的空间。
    需要注意的是枚举s的时候需要从后往前,不能从前往后,否则会变成完全背包(每个精灵有无数只),而本题需要的是01背包(每个精灵只有一只)。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e4+5;
    
    struct gg{
    	int v,w;
    }g[N];
    int dp[N];
    int cnt[N];
    void solve()
    {
    	memset(dp,0,sizeof(dp));
    	memset(cnt,0,sizeof(cnt));
    	int n,s;
    	cin>>n>>s;
    	for(int i=1;i<=n;i++)cin>>g[i].w>>g[i].v;
    	for(int i=1;i<=n;i++){
    		for(int j=s;j>=g[i].w;j--){//从s开始
    			if(dp[j-g[i].w]+g[i].v>dp[j]){
    				dp[j]=dp[j-g[i].w]+g[i].v;
    				cnt[j]=cnt[j-g[i].w]+1;				
    			}
    		}
    	}
    	cout<<dp[s]<<" "<<cnt[s]<<endl;
    }
    	
    int main()
    {
    	ios::sync_with_stdio(false);	
    	int t;
    	cin>>t;
    	while(t--)solve();
    	return 0;
    }
    
  • 相关阅读:
    Entity Framework底层操作封装V2版本号(3)
    从Java到C++——union的使用方法
    静态链接库与动态链接库
    51Nod1446 限制价值树
    2018-8-10-win10-uwp-获取文件夹出错
    2018-8-10-win10-uwp-获取文件夹出错
    2018-10-22-win10-uwp-自定义控件入门
    2018-10-22-win10-uwp-自定义控件入门
    2019-9-2-C#同步方法转异步
    2019-9-2-C#同步方法转异步
  • 原文地址:https://www.cnblogs.com/LiangYC1021/p/13169974.html
Copyright © 2011-2022 走看看