|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 zhangjinxuan 于 2023-8-20 17:24 编辑
梦想星际舰队第7关 && FCOI #6 题解
第四题:迷宫
题目描述
你带着一个 sumv 容积的背包来到了一个 a 行 b 列的迷宫,你可以向下或者向右移动,但不能出界或者碰到障碍。
迷宫中有 n 种宝藏,还有 m 个障碍。
第 i 种宝藏的位置是 x1 i 行 y1 i 列,每个的体积是 vi ,但为你带来的收益每个都是 w_i ,一共有 l_i 个,当你的位置有一种或一些宝藏,你可以拾取这种的零个或多个,每获取一个就会获得 wi 的收益,同时,每一个对应的宝藏会占用你背包 vi,若背包占用满了或无法放下时,它将无法放入,你也得不到这个收益。
当然,不同种类的宝藏的位置可能会重合。
第 i 个障碍的位置是 x2 i 行 y2 i 列,保证宝藏的位置不是障碍的位置。
现在给你这个迷宫的信息,即障碍、大小、宝藏的信息,请求出,如果要从 1 行 1 列出发,到迷宫上任意非障碍的一点,你获得的最大收益是多少?
输入格式
- a b
- n m sumv
- x1_1 y1_1 v_1 w_1 l_1
- x1_2 y1_2 v_2 w_2 l_2
- ...
- x1_n y1_n v_n w_n l_n
- x2_1 y2_1
- ...
- x2_m y2_m
复制代码
输入输出样例
输入 #1
- 1 1
- 5 0 10
- 1 1 2 1 2
- 1 1 5 8 2
- 1 1 2 4 5
- 1 1 3 9 2
- 1 1 4 3 2
复制代码
输出 #1
输入 #2
- 3 5
- 5 2 10
- 2 2 2 3 1
- 2 1 1 2 2
- 2 3 5 4 3
- 3 4 4 6 1
- 2 5 3 5 2
- 1 2
- 3 2
复制代码
输出 #2
样例解释 1
即正常的多重背包问题。
样例解释 2
其一最优解路线如下:
(1,1)-(2,1)-(2,2)-(2,3)-(2,4)-(2,5)
拾取的物品分别是在 (2,1) 位置上的体积 1,收益 2 的 2 个宝藏,在 (2,2) 位置上的体积 2,收益 3 的 1 个宝藏,在 (2,5) 位置上的体积 3,收益 5 的 2 个宝藏。
消耗的体积:1×2+2×1+3×2=10,刚刚好。
获得的收益:2×2+3×1+5×2=17,故输出 17。
数据范围
对于 20% 的数据,保证 a,b=1,1。对于 30% 的数据,保证 a,b≤5。另外 20% 的数据,
保证 1≤l≤2。对于100% 的数据,保证 1≤a,b≤100,0≤m≤a×b,n≤1000,1≤v,w≤10^9,1≤l≤10^6,1≤sumv≤10000
坐标合法,且所有输入为整数。
其他说明
本题目zhangjinxuan原创,测评链接 https://hydro.ac/d/gaoshan/p/FCR6maze
答案与解析
[/hide]
最佳战士排行榜
本帖子不设本奖励。
- #include <bits/stdc++.h>
- using namespace std;
- int n, m, a, b;
- int s[101][101];
- int x, y, v, w, smv, l;
- long long f[5][101][10001], ans;
- struct Info {
- int v, w, l;
- };
- vector<Info> t[101][101];
- int main() {
- scanf("%d%d", &a, &b);
- scanf("%d%d%d", &n, &m, &smv);
- for (int i = 1; i <= n; ++i) {
- scanf("%d%d%d%d%d", &x, &y, &v, &w, &l);
- t[x][y].push_back({v, w, l});
- }
- for (int j = 1; j <= m; ++j) {
- scanf("%d%d", &x, &y);
- s[x][y] = -1;
- }
- for (int i = 1; i <= a; ++i) {
- for (int j = 1; j <= b; ++j) {
- if (s[i][j] == -1) continue;
- int li = (i - 1) % 5;
- int ri = i % 5;
- int lj = j - 1;
- int rj = j;
- for (int k = 0; k <= smv; ++k) {
- long long tmp = 0;
- if (s[i - 1][j] != -1) {
- tmp = max(f[li][rj][k], tmp);
- }
- if (s[i][j - 1] != -1) {
- tmp = max(f[ri][lj][k], tmp);
- }
- f[ri][rj][k] = max(f[ri][rj][k], tmp);
- }
- for (auto th : t[i][j]) {
- int c[101] = {}, tot = 0, tmp = 1;
- while (th.l >= tmp) {
- c[++tot] = tmp;
- th.l -= tmp;
- tmp *= 2;
- }
- if (th.l) c[++tot] = th.l;
- for (int ii = 1; ii <= tot; ++ii) {
- for (int k = smv; k >= 1ll * th.v * c[ii]; --k) {
- f[ri][rj][k] = max(f[ri][rj][k], f[ri][rj][k - th.v * c[ii]] + th.w * c[ii]);
- }
- }
- }
- ans = max(ans, f[ri][rj][smv]);
- }
- }
- printf("%lld", ans);
- return 0;
- }
复制代码
AC 
|
|