2017山东夏令营测验 D5T1 题解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017山东夏令营测验 D5T1 题解相关的知识,希望对你有一定的参考价值。

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。

小菜一碟的背包
题目描述
有n头奶牛,每头奶牛有食量w[i]和产奶量v[i],每天能够提供W千克草料。选取奶牛使产奶总量尽可能大,问最大是多少。
输入格式
第一行两个整数 ,表示奶牛的数量和每天最多能提供的草
接下来i行,每行两个整数,第i行表示第I头奶牛的产奶量和食量
输出格式
仅一行,输出一个整数,表示每天最大的总产奶量
输入样例
8 40
10 9
12 11
11 12
10 10
8 11
7 9
8 10
9 10
输出样例
41
限制与约定
对于所有数据,1 ≤ n ≤ 100,1 ≤ wi,W ≤ 10^9,1 ≤ vi ≤ 10^7,w1 ≤ wi ≤ w1 + 3.

分析:

并不是小菜一碟...

由于W的范围太大,不能用常规的01背包来做。

注意到w[]的波动范围很小,所以我们可以将所有的w减去一个基数,f[i][j][k]表示前i头奶牛中选取j头,其食量(减去基数之后的)和为k。

逆向转移。状态转移方程:f[i][j][k] = max(f[i+1][j][k],f[i+1][j+1][k+w[i+1]]+v[i+1]);

 

AC代码:

 

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 
 5 const int MAXN = 105;
 6 
 7 inline void read(int &x)
 8 {
 9     char ch = getchar(),c = ch;x = 0;
10     while(ch < 0 || ch > 9) c = ch,ch = getchar();
11     while(ch >= 0 && ch <= 9) x = (x<<1)+(x<<3)+ch-0,ch = getchar();
12     if(c == -) x = -x;
13 }
14 long long f[MAXN][MAXN][305];
15 bool vis[MAXN][MAXN][305];
16 //choose j cows sum value
17 int w[MAXN],v[MAXN],n,W;
18 int mn = 2e9;
19 
20 int dp(int i,int j,int k)
21 {
22     if (1LL*j*mn+k>W) return -2e9;//装不下了 
23     if(i == n)    return 0;//已经全部尝试完 
24     if(vis[i][j][k]) return f[i][j][k];
25     vis[i][j][k] = true;
26     return f[i][j][k] = std::max(dp(i+1,j,k),dp(i+1,j+1,k+w[i+1])+v[i+1]);
27 }
28 
29 int main()
30 {
31     read(n),read(W);
32     for(int i = 1;i <= n;++ i)
33         read(v[i]),read(w[i]),mn = std::min(w[i],mn);
34     mn --;//mn就是基准数 
35     for(int i = 1;i <= n;++ i)
36         w[i] -= mn;
37     printf("%d\n",dp(0,0,0));
38 }

 

以上是关于2017山东夏令营测验 D5T1 题解的主要内容,如果未能解决你的问题,请参考以下文章

2015山东信息学夏令营 Day5T3 路径

2017省夏令营Day8 bfs,并查集

道路重建 (2018山东冬令营)

山东冬令营2018:贪心专练

2017省夏令营Day6 dp

编程试题练习:2018计算机学科-夏令营上机考试题解