【数模】2020B 穿越沙漠
许久不见动态规划,没想到数模碰到了,就想水篇久违的题解。
至于为什么不放完整论文?肯定是做的不是很好啦,话说原来数模出题人也会是ACMer吗
穿越沙漠
题意
考虑如下的小游戏:玩家凭借一张地图,利用初始资金购买一定数量的水和食物(包括食品和其他日常用品),从起点出发,在沙漠中行走。途中会遇到不同的天气,也可在矿山、村庄补充资金或资源,目标是在规定时间内到达终点,并保留尽可能多的资金。
游戏的基本规则如下:
(1)以天为基本时间单位,游戏的开始时间为第0天,玩家位于起点。玩家必须在截止日期或之前到达终点,到达终点后该玩家的游戏结束。
(2)穿越沙漠需水和食物两种资源,它们的最小计量单位均为箱。每天玩家拥有的水和食物质量之和不能超过负重上限。若未到达终点而水或食物已耗尽,视为游戏失败。
(3)每天的天气为“晴朗”、“高温”、“沙暴”三种状况之一,沙漠中所有区域的天气相同。
(4)每天玩家可从地图中的某个区域到达与之相邻的另一个区域,也可在原地停留。沙暴日必须在原地停留。
(5)玩家在原地停留一天消耗的资源数量称为基础消耗量,行走一天消耗的资源数量为基础消耗量的2倍。
(6)玩家第0天可在起点处用初始资金以基准价格购买水和食物。玩家可在起点停留或回到起点,但不能多次在起点购买资源。玩家到达终点后可退回剩余的水和食物,每箱退回价格为基准价格的一半。
(7)玩家在矿山停留时,可通过挖矿获得资金,挖矿一天获得的资金量称为基础收益。如果挖矿,消耗的资源数量为基础消耗量的3倍;如果不挖矿,消耗的资源数量为基础消耗量。到达矿山当天不能挖矿。沙暴日也可挖矿。
(8)玩家用剩余的初始资金或挖矿获得的资金在村庄去其他地方是可以购买水和食物,每箱价格为基准价格的2倍。
请根据游戏的设定,假设只有一名玩家,在整个游戏时段内每天天气状况事先全部已知,试给出一般情况下玩家的最优路径。
最优解为到终点还有10470金钱,用时24天
最优解为到终点时还有12730金钱,用时30天
思路
很明显的一个动态规划
设状态dp[k][j][w][f]代表第k天时在第j个点剩余水为w箱剩余食物为f箱的最大资金,则:
就是遍历第每天在终点的所有水、食物的状态求最大值。
初始值设定
由于起始点可以在起点购买物资,则有初始状态:
其中$cost_water$,$cost_food$ 为购买水和食物消耗的钱。
这里假设起始为第0天,则第一天天气影响的是从第0天到第1天。
状态转移方程
当第k天人在村庄j时:
第k天为沙暴天气:
dp[k+1][j][w+ww-xh_water[tq]][f+ff-xh_food[tq]]}=max(dp[k][j][w][f]-2*ww*cost_water-2*ff*cost_food
非沙暴天气:
从j点走到jj点
dp[k+1][jj][w+ww-xh_water[tq]][f+ff-xh_food[tq]]}=max(dp[k][j][w][f]-2*ww*cost_water-2*ff*cost_food
当第k天人在矿山j时:
挖矿:
dp[k+1][j][w-dig*xh_water[tq]][f-dig*xh_food[tq]]=max(dp[k][j][w][f]+1000)
第k天为沙暴天气:
dp[k+1][j][w-xh_water[tq]][f-xh_food[tq]]=max(dp[k][j][w][f])
第k天为非沙暴天气:
dp[k+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]=max(dp[k][jj][w][f])
当第k天人在其他地区时
第k天为沙暴天气:
dp[k+1][j][w-xh_water[tq]][f-xh_food[tq]]=max(dp[k][j][w][f])
第k天为非沙暴天气:
从j点走到jj点
dp[k+1][jj][w-walk*xh_water[tq]][f-walk*xh_food[tq]]=max(dp[k][j][w][f])
优化
虽然没有评测姬,但是作为曾经的Acmer不能容忍运行样例大于1s,所以只会转移方程还是过不了这题。
显然由样例可知,点 太 多 了!!!,我们考虑删点。
稍微思考一下就知道这题有几个隐含条件:
- 除了回村庄补充物资,不会走回头路。
- 除了挖矿和沙尘暴不会在原地停留。
- 只会走关键点之间的最短路径
故我们只需要将关键点之间的最短路求出,最短路经过的点才被认为是有效点,最短路经过的边才被认为是有效边,这样就可以化简图了。
化简之后的路径图如下:
可见有效点只有10个大大减少了时间复杂度,但是点数超过13仍会爆空间和时间,空间可以试试滚动数组优化,时间我是没什么好办法了。
代码
第一关
代码
|
结果
日期 | 所在区域 | 剩余资金数 | 剩余水量 | 剩余食物量 |
---|---|---|---|---|
0 | 1 | 5780 | 178 | 333 |
1 | 25 | 5780 | 162 | 321 |
2 | 26 | 5780 | 146 | 309 |
3 | 27 | 5780 | 136 | 295 |
4 | 27 | 5780 | 126 | 285 |
5 | 21 | 5780 | 116 | 271 |
6 | 9 | 5780 | 100 | 259 |
7 | 9 | 5780 | 90 | 249 |
8 | 15 | 5780 | 80 | 235 |
9 | 14 | 4150 | 227 | 223 |
10 | 12 | 4150 | 211 | 211 |
11 | 12 | 5150 | 181 | 181 |
12 | 12 | 6150 | 157 | 163 |
13 | 12 | 7150 | 142 | 142 |
14 | 12 | 8150 | 118 | 124 |
15 | 12 | 9150 | 94 | 1106 |
16 | 12 | 10150 | 70 | 88 |
17 | 12 | 10150 | 60 | 78 |
18 | 12 | 10150 | 50 | 68 |
19 | 12 | 11150 | 26 | 50 |
20 | 14 | 11150 | 10 | 38 |
21 | 15 | 11150 | 0 | 24 |
22 | 9 | 10470 | 26 | 26 |
23 | 21 | 10470 | 10 | 14 |
24 | 27 | 10470 | 0 | 0 |
第二关
代码
与第一关不同的是点的数量变多了,空间复杂度过不去。我只好把path删了一个变量money才勉强过去。就是后面要手算money很麻烦
后来想应该可以滚动数组的,但是不想写了。毕竟已经退役了
#include<bits/stdc++.h> |
结果
日期 | 所在区域 | 剩余资金数 | 剩余水量 | 剩余食物量 |
---|---|---|---|---|
0 | 1 | 5300 | 130 | 405 |
1 | 2 | 5300 | 114 | 393 |
2 | 3 | 5300 | 98 | 381 |
3 | 4 | 5300 | 88 | 367 |
4 | 4 | 5300 | 78 | 357 |
5 | 12 | 5300 | 68 | 343 |
6 | 21 | 5300 | 52 | 331 |
7 | 21 | 5300 | 42 | 321 |
8 | 29 | 5300 | 32 | 307 |
9 | 30 | 5300 | 16 | 295 |
10 | 39 | 5300 | 0 | 283 |
11 | 39 | 5200 | 0 | 273 |
12 | 30 | 3410 | 163 | 261 |
13 | 30 | 4410 | 148 | 240 |
14 | 30 | 5410 | 124 | 222 |
15 | 30 | 6410 | 100 | 204 |
16 | 30 | 7410 | 76 | 186 |
17 | 30 | 8410 | 46 | 156 |
18 | 30 | 9410 | 16 | 126 |
19 | 39 | 9410 | 0 | 114 |
20 | 47 | 5730 | 180 | 188 |
21 | 55 | 5730 | 170 | 174 |
22 | 55 | 6730 | 155 | 153 |
23 | 55 | 7730 | 131 | 135 |
24 | 55 | 8730 | 116 | 114 |
25 | 55 | 9730 | 86 | 84 |
26 | 55 | 10730 | 62 | 66 |
27 | 55 | 11730 | 47 | 45 |
28 | 55 | 12730 | 32 | 24 |
29 | 56 | 12730 | 16 | 12 |
30 | 12 | 12730 | 0 | 0 |
末尾的哔哔
再优化
后来和lms交流后发现自己村庄搜索代码写挫了,因为是递推的所以不用枚举购买的水和食物量,而是分别购买1箱水和1箱食物的状态转移。这样就能控制程序1s了。
难度
从oi来看的话我个人认为单纯dp应该有提高+难度?但是考虑到优化复杂度应该有黑题左右的难度了。我是有什么资格评价的哇
从ACM来看的话如果有时间限制的话应该是个银牌题吧,没有时间限制就是个铜牌题。本菜鸡做了大半天…
本文链接:https://dummerfu.top/p/54346.html
版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0许可协议 转载请注明出处!