宁波工程学院2020新生校赛J - 小梁的背包(01背包)
链接:https://ac.nowcoder.com/acm/contest/6106/J
来源:牛客网
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
小梁来到了伽勒尔地区并参加了联盟赛热身赛,比赛小岛上有n个精灵散落在岛上各处,她有一个大小为s的背包,每个精灵的战斗值为v,体积为w
请问在她临走之前背包内宝可梦的战斗力总和最多为多少,并输出其战斗值总和sum以及背包内的精灵数量ans。
输入描述:
输入一个整数T(1≤T≤200)表示测试组数
每组数据的第一行有两个整数 n,s(1≤n,s≤104 )
接下来有n行数据,每行两个代表宝可梦体积w和战斗值v (1≤w,v≤104 )
输出描述:
输出T组,每组一行sum 和 ans
示例1
输入
1
5 5
1 3
2 5
1 2
4 2
6 1
输出
10 3
题目大意:
给出一个体积为s的背包,然后给出n个精灵的战斗力和体积,求背包内的精灵战斗力总和最大是多少,并输出背包内有几只精灵。
解题思路:
01背包模板题,但是这道题是1e4的,显然二维dp会超内存,优化一下优化到一维,用结构体存数据,dp[v].val表示体积小于v的情况下,战斗力最大是多少,dp[v].ans表示当前状态下有多少个精灵。
状态转移方程:
dp[i].val=dp[j-v[i]].val+w[i]
dp[i].ans=dp[j-v[i]].ans+1
AC代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int _max=1e4+50;
int w[_max],v[_max];
struct node { int val,ans; };
node dp[_max];
int main()
{
int t;
cin>>t;
while(t--)
{
memset(dp,0,sizeof dp);
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>v[i]>>w[i];
for(int i=1;i<=n;i++)
for(int j=m;j>=v[i];j--)//01背包原地滚动从后往前枚举
{
if(dp[j].val<dp[j-v[i]].val+w[i])
{
dp[j].val=dp[j-v[i]].val+w[i];
dp[j].ans=dp[j-v[i]].ans+1;
}
}
cout<<dp[m].val<<" "<<dp[m].ans<<endl;
}
//system("pause");
return 0;
}