Luogo P2616 [USACO10JAN]Buying Feed, II S
rsdbk_husky · · 题解
放在前面:为对应“普及-”的难度,本文讲解的是
零. 安利:
安利一下我的博客。
一. 变量声明:
二. 思路
1. 思考解法
- 路线上后面的商店不会影响路线前半部分的最优解,符合无后效性。
- 有最大容量
W ,有可选择的物品,每个物品有重量和价值,明显是背包类问题。
所以考虑背包 DP。
2. 初始状态
3. 结束状态
三. 代码
代码中有一些例如构造函数和重载运算符一样的技巧,这些暂时不会也不妨碍理解算法,只需看 main 函数中的内容就行了。
#include<bits/stdc++.h>
using namespace std;
#define re register
const int MAXn = 500;
const int MAXW = 10000;
template <class T> //模板函数
inline void read(T &a) {
register char c;while (c = getchar(), c < '0' || c >'9');register T x(c - '0');while (c = getchar(), c >= '0' && c <= '9')x = (x << 1) + (x << 3) + c - '0';a = x;
}
inline int min(int a, int b) {
return a < b ? a : b;
}
struct Shop {
int x;
int w;
int v;
Shop(): x(0), w(0), v(0){} //构造函数
Shop(int x_, int w_, int v_): x(x_), w(w_), v(v_) {} //同上
inline bool operator < (Shop &a) { //重载运算符
return this->x < a.x;
}
};
Shop shop[MAXn + 10];
int W, n, d[MAXn + 10][MAXW + 10];
int main() {
int E;
read(W), read(E), read(n);
shop[0] = Shop(0, 0, 0); //本人将起点和终点(家)时当做食物数为 0 的商店,这样能避免特判,所以“home”就是n+1
for (re int i = 1, x, w, v; i <= n; ++i) {
read(x), read(w), read(v);
shop[i] = Shop(x, w, v);
}
shop[n + 1] = Shop(E, 0, 0); //同上
sort(shop, shop + n + 2);
memset(d, 0x3f, sizeof(d));
d[0][0] = 0;
for (re int i = 1; i <= n + 1; ++i) { //i:当前阶段是在哪个店
for (re int j = W; j >= 0; --j) { //j:当前状态要求车上有多少饲料
for (re int k = 0; k <= shop[i].w; ++k) { //k:当前转移中要从本店买多少饲料
if (j < k) continue;
d[i][j] = min(d[i][j], d[i - 1][j - k] + (shop[i].x - shop[i - 1].x) * (j - k) + k * shop[i].v);
}
}
}
printf("%d", d[n + 1][W]);
}