1. 程式人生 > >洛谷 #1941. 飛揚的小鳥

洛谷 #1941. 飛揚的小鳥

題意

玩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; }