题目链接:
poj:点击打开链接
hdu:点击打开链接
题意:
一个人要买 t 元钱的东西;
他有 n 种钱;
每种钱有 v[i] 的价值;
每种钱有 w[i] 个;
然后他要在花 t 这么多钱的同时用最少的硬币数量;
并且商店找回的硬币数量也是最少的;
如果不能买或者找不回那么多钱就输出 -1;
理解:
两题题意一模一样;
所以放一堆写题解;
并不造怎么做;
神解释说,多重背包加完全背包基础题;
多重背包很明显从顾客一方就可以看出;
而完全背包是从商店一方看出来的;
因为商店的硬币数是无限的;
这样在某一个价值 i 的状态下;
就存在顾客的最少硬币数 muldp[i] 加上商店的最少硬币数 fuldp[i - t] 是最少使用的硬币数;
多重背包递推式:muldp[i] = min(muldp[i], muldp[i - mul * v[i]] + mul);
完全背包递推式:fuldp[i] = min(fuldp[i], fuldp[i - v[i]] + 1);
其中的值根据代码定义;
初始值都为无穷大;
muldp[0] = 0;
fuldp[0] = 0;
ans = min(muldp[i] + fuldp[i - t]);
其中这里有个最大值边界问题;
因为 t 是正好用那么多钱;
而实际要多给钱,然后商店找钱;
所以要估算最多要多给多少钱;
但一般算一下都不会太大,所以给个几万就行了;
其实因为价值最大是 120;
那么超过这个价值的值商店都能找回来;
所以只需算到 t + 120;
也不知道这种说法对不对。。
代码如下:
poj:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int MIN_INF = 1e-7;
const int MAX_INF = (1e9) + 7;
#define X first
#define Y second
int muldp[555555], fuldp[555555];
int v[222], w[222];
int main() {
int n, t;
cin >> n >> t;
for (int i = 0; i < n; ++i) {
cin >> v[i];
}
for (int i = 0; i < n; ++i) {
cin >> w[i];
}
fill(muldp, muldp + 200100, MAX_INF);
fill(fuldp, fuldp + 200100, MAX_INF);
muldp[0] = 0;
for (int i = 0; i < n; ++i) {
int num = w[i];
for (int k = 1; num > 0; k <<= 1) {
int mul = min(num, k);
for (int j = 55000; j >= mul * v[i]; --j) {
muldp[j] = min(muldp[j], muldp[j - mul * v[i]] + mul);
}
num -= k;
}
}
fuldp[0] = 0;
for (int i = 0; i < n; ++i) {
for (int j = v[i]; j < 55001; ++j) {
fuldp[j] = min(fuldp[j], fuldp[j - v[i]] + 1);
}
}
int ans = MAX_INF;
for (int i = t; i < 55001; ++i) {
ans = min(ans, muldp[i] + fuldp[i - t]);
}
cout << (ans == MAX_INF ? -1 : ans) << endl;
return 0;
}
hdu:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int MIN_INF = 1e-7;
const int MAX_INF = (1e9) + 7;
#define X first
#define Y second
int muldp[555555], fuldp[555555];
int v[222], w[222];
int main() {
int n, t, I = 1;
while (cin >> n >> t && n + t) {
for (int i = 0; i < n; ++i) {
cin >> v[i];
}
for (int i = 0; i < n; ++i) {
cin >> w[i];
}
fill(muldp, muldp + 200100, MAX_INF);
fill(fuldp, fuldp + 200100, MAX_INF);
muldp[0] = 0;
for (int i = 0; i < n; ++i) {
int num = w[i];
for (int k = 1; num > 0; k <<= 1) {
int mul = min(num, k);
for (int j = 55000; j >= mul * v[i]; --j) {
muldp[j] = min(muldp[j], muldp[j - mul * v[i]] + mul);
}
num -= k;
}
}
fuldp[0] = 0;
for (int i = 0; i < n; ++i) {
for (int j = v[i]; j < 55001; ++j) {
fuldp[j] = min(fuldp[j], fuldp[j - v[i]] + 1);
}
}
int ans = MAX_INF;
for (int i = t; i < 55001; ++i) {
ans = min(ans, muldp[i] + fuldp[i - t]);
}
cout << "Case " << I++ << ": ";
cout << (ans == MAX_INF ? -1 : ans) << endl;
}
return 0;
}