码迷,mamicode.com
首页 > 其他好文 > 详细

2017山东夏令营测验 D5T1 题解

时间:2017-08-19 20:10:24      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:div   接下来   value   color   --   转移   c代码   原创   范围   

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

小菜一碟的背包
题目描述
有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 题解

标签:div   接下来   value   color   --   转移   c代码   原创   范围   

原文地址:http://www.cnblogs.com/shingen/p/7397593.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!