洛谷 P2918 [USACO08NOV]买干草Buying Hay 题解
P2918 [USACO08NOV]买干草Buying Hay
题目描述
Farmer John is running out of supplies and needs to purchase H (1 <= H <= 50,000) pounds of hay for his cows.
He knows N (1 <= N <= 100) hay suppliers conveniently numbered 1..N. Supplier i sells packages that contain P_i (1 <= P_i <= 5,000) pounds of hay at a cost of C_i (1 <= C_i <= 5,000) dollars. Each supplier has an unlimited number of packages available, and the packages must be bought whole.
Help FJ by finding the minimum cost necessary to purchase at least H pounds of hay.
约翰的干草库存已经告罄,他打算为奶牛们采购\(H(1 \leq H \leq 50000)\)镑干草.
他知道\(N(1 \leq N\leq 100)\)个干草公司,现在用\(1\)到\(N\)给它们编号.第\(i\)公司卖的干草包重量 为\(P_i (1 \leq P_i \leq 5,000)\) 磅,需要的开销为\(C_i (1 \leq C_i \leq 5,000)\) 美元.每个干草公司的货源都十分充足, 可以卖出无限多的干草包.
帮助约翰找到最小的开销来满足需要,即采购到至少\(H\)镑干草.
输入格式
-
Line 1: Two space-separated integers: N and H
-
Lines 2..N+1: Line i+1 contains two space-separated integers: P_i and C_i
输出格式
- Line 1: A single integer representing the minimum cost FJ needs to pay to obtain at least H pounds of hay.
输入输出样例
输入 #1
2 15
3 2
5 3
输出 #1
9
说明/提示
FJ can buy three packages from the second supplier for a total cost of 9.
【思路】
完全背包
很有意思的一道背包题目
【题目大意】
给你干草重量和花费,每种都是无限买
买不少于h 镑干草花最少的钱
【题目分析】
很显然是可以用完全背包来做的
数据范围5000*100完全没有问题
然后就可以按照完全背包的模板来跑了、
bb[i]表示i镑干草花的最少的钱
是可以由i-a[x]的情况推过来的
(a[x]表示任意一种干草)
是bb[i-a[x]]+c[x]的最小情况推过来的
然后发现只有30分
【错误原因】
至少H镑干草这一点很又迷惑性
会情不自禁忽略掉他
但其实这才是最重要的一个地方
至少H那就是可以买比H镑多的干草
但是比H镑多又有一种限制
因为一捆干草最多是5000镑
所以最多不能超过H+5000镑
为什么呢??
因为如果超出了5000镑
那一定有一捆干草是完全多余出来的
也就是可以拿掉任意一捆干草之后还是满足至少H镑干草的
因为任意一捆干草都是小于5000镑的
H加上一个大于等于5000的数之后再减去一个小于等于5000的数
还是满足至少H镑干草的
所以多出5000之后的范围那就是没有必要的了
所以跑完全背包的时候跑H+5000
然后最后答案也是H-H+5000这个范围内的最小值
【完整代码】
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int Max = 55004;
int bb[Max],p[105],c[105];
int main()
{
int n,h;
cin >> n >> h;
memset(bb,999999,sizeof(bb));
for(register int i = 1;i <= n;++ i)
cin >> p[i] >> c[i];
bb[0] = 0;
for(register int i = 1;i <= n;++ i)
for(register int j = p[i];j <= h + 5000;++ j)
bb[j] = min(bb[j],bb[j - p[i]] + c[i]);
int M = 0x7fffffff;
for(register int i = h;i <= h + 5000;++ i)
M = min(M,bb[i]);
cout << M << endl;
return 0;
}