[THUPC 2023 初赛] 背包

题目描述

本题中,你需要解决完全背包问题。

\(n\) 种物品,第 \(i\) 种物品单个体积为 \(v_i\)、价值为 \(c_i\)

\(q\) 次询问,每次给出背包的容积 \(V\),你需要选择若干个物品,每种物品可以选择任意多个(也可以不选),在选出物品的体积的和恰好\(V\) 的前提下最大化选出物品的价值的和。你需要给出这个最大的价值和,或报告不存在体积和恰好为 \(V\) 的方案。

为了体现你解决 NP-Hard 问题的能力,\(V\) 会远大于 \(v_i\),详见数据范围部分。

输入格式

第一行两个整数 \(n,q\),表示物品种数和询问次数。

接下来 \(n\) 行每行两个整数 \(v_i,c_i\) 描述一种物品。

接下来 \(q\) 行每行一个整数 \(V\) 描述一次询问中背包的体积。

输出格式

对于每组询问输出一行一个整数。若不存在体积和恰好为 \(V\) 的方案,输出 -1;否则输出最大的选出物品的价值和。

样例 #1

样例输入 #1

2 2
6 10
8 15
100000000001
100000000002

样例输出 #1

-1
187500000000

提示

样例解释 1

第二组询问的最优方案为:选择 \(3\) 个物品 \(1\)\(12499999998\) 个物品 \(2\)

子任务

对于所有测试数据,\(1 \le n \le 50, 1 \le v_i \le 10^5, 1 \le c_i \le 10^6, 1 \le q \le 10^5, 10^{11} \le V \le 10^{12}\)

题目来源

来自 2023 清华大学学生程序设计竞赛暨高校邀请赛(THUPC2023)初赛。

思考当 \(V\) 非常大的时候,选的数有没有什么规律?

容易想到,一定有一个物品被选了很多次。结合 \(n\le50\),猜测需要去枚举哪种物品选择了很多次。

然后大概减到一定次数之内,就不一定是拼命选这个数了。预处理出 \(v_i\le 5\times 10^6\) 以内完全背包的答案。每次选物品选到容量小于等于 \(5\times 10^6\),然后就用完全背包的方法去选就行了。

#include
using namespace std;
const int N=5e6+5,M=5e6;
int n,q;
long long s,dp[N],v[N],c[N],w,ans,k;
int main()
{
    memset(dp,-0x7f,sizeof(dp));
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
        scanf("%d%d",v+i,c+i);
    dp[0]=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=v[i];j

你可能感兴趣的:(动态规划,算法,图论)