原題傳送門
此題暴力dp可過
表示到的最小點擊數
非常的轉移方程
的枚舉順序注意一下,第一個的完全揹包,第二個是01揹包
另外,注意一下往上突破天花板的特殊情況
是否到達終點隨便判斷一下就好了
Code:
#include <bits/stdc++.h>
#define maxn 10010
using namespace std;
int n, m, k, x[maxn], y[maxn], L[maxn], H[maxn], dp[maxn][2010], flag[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int main(){
n = read(), m = read(), k = read();
for (int i = 1; i <= n; ++i) x[i] = read(), y[i] = read(), H[i] = m + 1;
int p;
for (int i = 1; i <= k; ++i) p = read(), L[p] = read(), H[p] = read(), flag[p] = 1;
memset(dp, 0x3f, sizeof(dp));
for (int i = 1; i <= m; ++i) dp[0][i] = 0;
for (int i = 1; i <= n; ++i){
for (int j = x[i] + 1; j <= m + x[i]; ++j) dp[i][j] = min(dp[i - 1][j - x[i]], dp[i][j - x[i]]) + 1;
for (int j = m + 1; j <= m + x[i]; ++j) dp[i][m] = min(dp[i][m], dp[i][j]);
for (int j = 1; j <= m - y[i]; ++j) dp[i][j] = min(dp[i][j], dp[i - 1][j + y[i]]);
for (int j = 1; j <= L[i]; ++j) dp[i][j] = dp[0][0];
for (int j = H[i]; j <= m; ++j) dp[i][j] = dp[0][0];
}
int ans = dp[0][0];
for (int i = 1; i <= m; ++i) ans = min(ans, dp[n][i]);
if (ans < dp[0][0]) printf("1\n%d\n", ans); else{
int ans = 0;
for (int i = n; i; --i){
int s = dp[0][0];
for (int j = 1; j <= m; ++j) s = min(s, dp[i][j]);
if (s < dp[0][0]) break;
ans += flag[i];
}
printf("0\n%d\n", k - ans);
}
return 0;
}