2019 GDUT Rating Contest II : Problem G. Snow Boots

题面:

G. Snow Boots

Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 256 megabytes
 
It’s winter on the farm, and that means snow! There are N tiles on the path from the farmhouse to the barn, conveniently numbered 1...N, and tile i is covered in fi feet of snow.
Farmer John starts off on tile 1 and must reach tile N to wake up the cows. Tile 1 is sheltered by the farmhouse roof, and tile N is sheltered by the barn roof, so neither of these tiles has any snow. But to step on the other tiles, Farmer John needs to wear boots!
In his foul-weather backpack, Farmer John has B pairs of boots, numbered 1...B. Some pairs are more heavy-duty than others, and some pairs are more agile than others. In particular, pair i lets FJ step in snow at most si feet deep, and lets FJ move at most di forward in each step.
Unfortunately, the boots are packed in such a way that Farmer John can only access the topmost pair at any given time. So at any time, Farmer John can either put on the topmost pair of boots (discarding his old pair) or discard the topmost pair of boots (making a new pair of boots accessible).
Farmer John can only change boots while standing on a tile. If that tile has f feet of snow, both the boots he takes off AND the boots he puts on must be able to withstand at least f feet of snow. Intermediate pairs of boots which he discards without wearing do not need to satisfy this restriction.
Help Farmer John minimize waste, by determining the minimum number of pairs of boots he needs to discard in order to reach the barn. You may assume that Farmer John is initially not wearing any boots.
 
Input
The first line contains two space-separated integers N and B (2 ≤ N,B ≤ 250).
The second line contains N space-separated integers. The ith integer is fi, giving the depth of snow on tile i (0 ≤ fi ≤ 109). It’s guaranteed that f1 = fN = 0.
The next B lines contain two space-separated integers each. The first integer on line i + 2 is si, the maximum depth of snow in which pair i can step. The second integer on line i + 2 is di, the maximum step size for pair i. It’s guaranteed that 0 ≤ si ≤ 109 and 1 ≤ di ≤ N −1.
The boots are described in top-to-bottom order, so pair 1 is the topmost pair in FJ’s backpack, and so forth.
 
Output
The output should consist of a single integer, giving the minimum number of boots Farmer John needs to discard. It’s guaranteed that it will be possible for FJ to make it to the barn.
 
Example
Input
10 4
0 2 8 3 6 7 5 1 4 0
2 3
4 2
3 4
7 1
Output
2
 

题目描述:

农夫想从农舍到谷仓(去喂奶牛?),去谷仓的路由N个瓷砖组成,按1-N编号,农夫从瓷砖1出发到瓷砖N,就可以到达谷仓了。由于下雪,瓷砖被雪不同程度地覆盖(有的瓷砖上积雪厚一点,有的薄一点)。因此,农夫必须穿靴子才能走到谷仓。在农夫的背包里,有B双靴子,按1-B编号。这些靴子有高的,也有矮的;有的跨一步跨远一点的(假如一双最多能跨x距离,那么,农夫可以穿着这双鞋子跨1距离,2距离...x距离),有的跨一步跨近一点。但是这个背包有个特点:只能拿背包最上面的靴子(这是什么背包来的,只能拿最上面的靴子  →_→),如果要拿背包下面的靴子,就只能把背包最上面的靴子丢掉,直到想拿到的靴子“浮”现在背包的最上面(有点像栈,可以用栈理解这个背包)。当前站的位置穿的鞋子高度不能低于积雪高度(低于的话靴子会“进”雪 ( ⊙ o ⊙ ) )。如果想要换一双靴子,就必须从背包拿出比当前积雪要高的靴子,然后穿上新鞋子,丢掉旧鞋子。求:怎样走才能使丢弃的鞋子数量最小,输出丢弃鞋子最小的数量

题目分析:

前言:这道题我看英文的时候各种看不懂,样例都看不懂(太渣了  ( /。\ )  ),到后面又忽略了一些细节,导致想了很久( (T_T) 
这道题是用动态规划去解决的,我们可以先看看样例是怎样的(看懂样例的可以无视我这渣渣解说):
首先,我们是在瓷砖1的位置,也就是:
由题意得知,我们在第1块瓷砖上是没有穿靴子的,这时我们穿上靴子1,背包情况:
然后往前面跨三块瓷砖,到达瓷砖4,也就是:
这时我们发现,这个靴子无论是跨几步瓷砖,都不能往前走了,所以我们要拿出新靴子,看能不能继续往前走。
这时我们丢弃了靴子1,穿上了靴子2,发现最多只能跨两个瓷砖,也就是最远距离到:
但是还是不行,因为和靴子1的问题一样,无论到哪个瓷砖靴子都会进“雪”(靴子高度不够)
所以,我们要再换一双鞋子,然后丢掉旧鞋子:
之后,我们就可以这样走:
这样农夫就穿着靴子3成功到达了终点,路上丢弃了两双鞋子
当然,刚开始的时候我们在出发时就从背包拿出靴子3(首先要丢弃靴子1和靴子2),然后直接穿着这个靴子到达终点。
也是只需要丢弃两双鞋子。
 
那这道题怎样用动态规划呢?一般动态规划的题有这样的特点:有多种途径求出到“最”值,而且当前第n个状态的最值可以由前n-1个状态的最值推算出来。特点1已经符合了,那么,我们可能会往动态规划方面去想:这个题目的问题:到达第N个瓷砖所需要丢弃的最少鞋子。子问题:到达第i个瓷砖所需要丢弃的最少鞋子(1 <= i < N)。这时需要考虑:假设知道了子问题的结果,怎样计算要求的问题。在这里就是:如果我到达了第i个瓷砖,怎样选才能到达第N个瓷砖?(我的代码是按照这个想法写的,想法不同代码也不同,动态规划的题AC代码不唯一)。在这里我是从前面去“更新”后面的值(即由前面瓷砖的最少丢弃鞋子“更新”到后面瓷砖的最少丢弃鞋子),dp[i]定义为到当前第i个瓷砖要丢弃的最少鞋子。这个dp[i]有个特点:由dp[i]还可以推测到第i个瓷砖时农夫正在穿的鞋子,为什么?因为背包比较特殊,取出来和穿过的鞋子不能再放回背包,所以农夫到第i个瓷砖穿的鞋子就是dp[i]+1,可以用上面解释样例的背包图理解一下这个。
 
解决完这些问题,基本上可以写出代码出来了,不过有一点要注意的是:从当前瓷砖到下一个瓷砖,如果要换鞋子的话,拿出鞋子的高度就不能低于当前瓷砖的雪的高度;如果要到下一个瓷砖,那么穿的鞋子一定不能低于下一个瓷砖的高度。有点人可能对dp数组的初始化有疑问:如果按照上面dp数组的解说,dp[1] = 0,即第1个瓷砖正在穿的鞋子是dp[1]+1 = 1,也就是第1双鞋子,但是题目说在第1个瓷砖没有穿鞋子啊。其实这个自己仔细考虑一下,第1个瓷砖穿与不穿第1双鞋子是不是没有影响?为了更方便我们计算,就假设在第1个瓷砖穿着第1双鞋子,也就是dp[1] = 0.
 
 
AC代码:
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <cmath>
 5 #include <set>
 6 #include <algorithm>
 7 using namespace std;
 8 const int inf = 0x3f3f3f3f;
 9 int n, b;
10 int f[255], s[255], d[255];
11 int dp[555];
12 
13 void test(){
14     cout <<endl;
15     for(int i = 1 ; i <= n ; i++){
16         printf("dp[%d] : %d\n", i, dp[i]);
17     }
18 }
19 
20 int main(){
21     cin >> n >> b;
22     for(int i = 1; i <= n; i++){
23         cin >> f[i];
24     }
25     for(int i = 1; i <= b; i++){
26         cin >> s[i] >> d[i];
27     }
28 
29     memset(dp, inf, sizeof(dp));
30     dp[1] = 0;  //第1个瓷砖丢弃0双鞋子,可以表示当前正在穿第1双鞋子
31 
32 
33     for(int i = 1; i <= n; i++){
34         int u = dp[i]+1;   //第i个瓷砖丢器正在穿第u双鞋子
35         for(int j = u; j <= b; j++){   //穿第j双鞋子到下一个瓷砖
36             for(int k = 1; k <= d[j]; k++){   //到第i+k个瓷砖
37                 if(f[i+k] <= s[j] && f[i] <= s[j]){  //穿的鞋子高于等于当前瓷砖和下一个瓷砖
38                     dp[i+k] = min(dp[i+k], j-1);   //穿第j双鞋子到第i+k个瓷砖,丢弃了j-1双鞋子
39                     //min()是更新操作,也就是如果其他瓷砖到达第i+k个瓷砖有更小的丢弃数量就更新为更小的
40                 }
41             }
42         }
43     }
44 
45     //test();
46 
47     cout << dp[n] << endl;
48 
49     return 0;
50 }
 
 
 

猜你喜欢

转载自www.cnblogs.com/happy-MEdge/p/10405028.html