网易2019笔试题-牛牛的背包
Posted 一米阳光213
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网易2019笔试题-牛牛的背包相关的知识,希望对你有一定的参考价值。
题目解析
-
核心思路
物品有n个,每个体积为 v[i],背包体积为 w. 每个物品有两种选择:放进背包,不放进背包。
状态设计:f(i,j):物品为前i个物品,背包体积为j,一共多少种放法。
状态转移:
如果第i个物品放进背包:f(i-1,j-v[i])
如果第i个物品不放进背包:f(i-1,j)
因此:
f(i,j) = f(i-1,j-v[i]) + f(i-1,j) -
难点分析:本题的数据量太大,1 <= w <= 2 * 10^9,空间消耗太大。同时,1 <= n <= 30,可以考虑时间换空间,用函数递归。
-
优化时间复杂度
不作优化,AC率为80%。
设 total 为所有物品体积之和,如果 total <= w,直接返回 2^n. 优化后,时间大幅降低,为 4ms. -
C++代码
#include <iostream>
#include<math.h>
using namespace std;
int n, v[32]; // n 表示物品的数量,v表示每个物品的体积
int w; // 背包的容量
typedef long long bint;
bint f(int n, int w) // n 表示前 n 个物品, w 表示 背包体积
if( w ==0 ) return 1;
if( n == 1 )
if( w < v[n] )
return 1; // 不放
else
return 2;
else if( w >= v[n] )
return f(n-1,w) + f(n-1,w-v[n]);
else
return f(n-1,w);
int main()
scanf("%d%d",&n,&w);
bint total = 0;
for(int i=0;i<n;i++)
scanf("%d",&v[i+1]); // 下标从1开始
total += v[i+1];
/************** 背包问题:多少种方法 ****************/
// dp[i][j]: 使用前i个物品,背包体积为j时,有多少种放法
// 状态转移方程:
// 如果第 i 个物品放进去, 有 dp[i-1][j-v[i]] 种放法
// 如果第 i 个物品不放进去,有 dp[i-1][j] 种放法
// dp[i][j] = dp[i-1][j-v[i]] + dp[i-1][j]
// 初始化:
// if j =0, dp[i][j] = 1
// if i =1, 讨论 v[1] 和 j 之间的关系
bint rs =0;
if( total <= w )
rs = (bint)pow(2,n);
else
rs = f(n,w);
cout << rs << endl;
return 0;
以上是关于网易2019笔试题-牛牛的背包的主要内容,如果未能解决你的问题,请参考以下文章