玄学题,dp。。。
用f[i][j]表示横坐标为i时高度为j的最少点击次数。
用正无穷来表示不可能达到这个状态。
于是我们可以分析出状态转移的方式:
上升——完全背包转移方式
下降——01背包转移方式
数据范围离谱,二维dp数组开10010(MAXN) * 2010可以过
#include <bits/stdc++.h>
#define N 10010
#define INF 0x3f3f3f3f
using namespace std;
inline int read() {
char c;
int res = 0, flag = 1;
for(; !isdigit(c); c = getchar())
if(c == '-') flag = -1;
for(; isdigit(c); c = getchar()) res = res * 10 + c - '0';
return res * flag;
}
int x[N], y[N], l[N], r[N];
bool vis[N];
int dp[N][2005];
int main() {
int n = read(), m = read(), k = read();
for(int i = 1; i <= n; i ++)
x[i] = read(), y[i] = read();
for(int i = 1; i <= n; i ++)
l[i] = 1, r[i] = m;
while(k --) {
int pop = read();
vis[pop] = 1, l[pop] = read() + 1, r[pop] = read() - 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]] + 1, 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 = r[i] + 1; j <= m; j ++)
dp[i][j] = dp[0][0];
}
int ans = dp[0][0];
for(int j = 1; j <= m; j ++)
ans = min(ans, dp[n][j]);
if(ans < dp[0][0]) printf("1\n%d\n", ans);
else {
int i, j;
for(i = n; i >= 1; i --) {
for(j = 1; j <= m; j ++)
if(dp[i][j] < dp[0][0]) break;
if(j <= m) break;
}
ans = 0;
for(int j = 1; j <= i; j ++)
if(vis[j]) ans ++;
printf("0\n%d\n", ans);
}
return 0;
}