洛谷 #1941. 飛揚的小鳥
阿新 • • 發佈:2018-11-26
題意
玩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;
}