ZJNU-OJ - 雪地靴1 (DP+细节处理)

雪地靴1

题目链接: ZJNU - 新生选拔赛 - snow boots1

题意

给出N块地砖,每块上有F[i]深度的雪,给你B双鞋子,每双鞋子都有两个属性: S[i] 最大可以承受的深度,D[i]最大可以跨过的距离。问题是要到达F[N]的地砖上最小要扔掉几双鞋子

注意

  1. 鞋子的顺序固定,无法交换顺序
  2. 在一块瓷砖上如果需要换鞋,那么换的鞋子和当前穿的鞋子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;
}

猜你喜欢

转载自blog.csdn.net/qq_41428565/article/details/80403807