雪地靴1
题目链接: ZJNU - 新生选拔赛 - snow boots1
题意
给出N块地砖,每块上有F[i]深度的雪,给你B双鞋子,每双鞋子都有两个属性: S[i] 最大可以承受的深度,D[i]最大可以跨过的距离。问题是要到达F[N]的地砖上最小要扔掉几双鞋子
注意
- 鞋子的顺序固定,无法交换顺序
- 在一块瓷砖上如果需要换鞋,那么换的鞋子和当前穿的鞋子S[i]都必须大于等于现在的雪的深度
思路
这是一道明显的DP问题,250的数据量正好可以满足DP中三次方的需要,我就开始按照自己原来经典的DP模板进行了就是
For 枚举鞋子
For 枚举格子
For 枚举步数
但是这里有一个很大的问题,就是注意点二。如果第i格时,我的第b双鞋无法换上,那么他在这个砖上他就无法换上鞋子,那么从这个点以后的砖,都不能从这点开始推过去,如果这个点可以换上鞋子,就从原来的两个序列中找。
非常重要。事实证明,完全按照题目意思的DP才不容易出BUG。
代码
#include <iostream>
#include <algorithm>
using namespace std;
int N, B, F[250], S[250], D[250], best = 9999;
bool dp[250][250]; // set of (location, boot) states we can reach
int solve(void)
{
dp[0][0] = 1;
for (int b=0; b<B; b++)
for (int i=0; i<N; i++) {
if (F[i] > S[b]) { dp[i][b] = false; continue; } // invalid state; snow too deep
for (int i2=0; i2<i; i2++)
if (dp[i2][b] && i2+D[b]>=i) dp[i][b] = true;
for (int b2=0; b2<b; b2++)
if (dp[i][b2]) dp[i][b] = true;
if (i==N-1 && dp[i][b]) return b;
}
}
int main(void)
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin >> N >> B;
for (int i=0; i<N; i++) cin >> F[i];
for (int i=0; i<B; i++) cin >> S[i] >> D[i];
cout << solve() << "\n";
return 0;
}