洛谷 #1941. 飞扬的小鸟

版权声明:转载请注明出处 https://blog.csdn.net/qq_41593522/article/details/84501871

题意

玩Flappy Bird,到天花板不能再往上,问最小点击屏幕次数 或 最多通过的管子数

题解

Dp,f[i][j]表示到i,j需要的最小步数,往上是完全背包,往下是01背包

调试记录

数组开得太大了

往上写成01背包了

#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 10005
#define INF 0x3f3f3f3f

using namespace std;

int x[maxn], y[maxn], n, m, k;

struct node{
    int a, b;
    bool f;
}h[maxn];

int f[maxn][maxn / 5];

int main(){
//	freopen("·ÉÑïµÄСÄñdata3.in", "r", stdin);
    scanf("%d%d%d", &n, &m, &k);
    
    for (int i = 1; i <= n; i++) scanf("%d%d", &x[i], &y[i]);
    for (int a, b, p, i = 1; i <= k; i++){
        scanf("%d%d%d", &p, &a, &b);
        h[p] = (node){a, b, true};
    }
    
 	for (int i = 1; i <= n; i++)
        for (int j = 0; j <= m; j++)
            f[i][j] = INF;
    for (int i = 1; i <= m; i++) f[0][i] = 0;
 	f[0][0] = INF;

    for (int i = 1; i <= n; i++){
        for (int j = x[i] + 1; j <= m + x[i]; j++) f[i][j] = min(f[i][j - x[i]] + 1, f[i - 1][j - x[i]] + 1);
        for (int j = m + 1; j <= m + x[i]; j++) f[i][m] = min(f[i][m], f[i][j]);
        for (int j = 1; j <= m - y[i]; j++) f[i][j] = min(f[i][j], f[i - 1][j + y[i]]);
        
        if (h[i].f){
            for (int j = 1; j <= h[i].a; j++) f[i][j] = INF;
            for (int j = h[i].b; j <= m; j++) f[i][j] = INF;
        }
    } 

    int ans = INF;
    for (int i = 1; i <= m; i++)
        ans = min(ans, f[n][i]);
    if (ans < INF){
        printf("1\n%d\n", ans);
        return 0;
    }
    
    ans = 0;
    for (int i = n - 1; i >= 0; i--){
        if (!h[i].f) continue;
        for (int j = 1; j <= m; j++)
            if (f[i][j] < INF){
                printf("0\n%d\n", k - ans);
                return 0;
            }
        ans++;
    }
    
    printf("0\n0\n");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41593522/article/details/84501871
今日推荐