分析
我们可以先定义状态 为在第 列,第 行所需要的最小点击次数。那么我们有如下转移 这个是如果选择点击的转移。 这个是不点的转移。那么我们通过滚动数组的技巧,第一种的转移优化到 。然后对于 的时候特判一下就好了。时间复杂度为 。对于障碍物我们直接赋值 。
代码
#include<bits/stdc++.h> using namespace std; int read() {int x;scanf("%d",&x);return x;} const int N = 21000,inf = 0x3f3f3f3f; struct Node { int p,l,h; }h[N]; int up[N],dw[N],n,m,K,f[N][1100],vis[N]; int main() { n = read();m = read();K = read(); for(int i = 1;i <= n;i++) up[i] = read(),dw[i] = read(); for(int i = 1;i <= K;i++) { h[i].p = read() + 1;h[i].l = read();h[i].h = read(); vis[h[i].p] = i; } memset(f,0x3f,sizeof(f)); for(int i = 1;i <= m;i++) f[1][i] = 0; for(int i = 2;i <= n + 1;i++) { for(int j = up[i - 1] + 1;j <= m;j++) f[i][j] = min(f[i][j],min(f[i-1][j - up[i - 1]],f[i][j - up[i - 1]]) + 1); for(int j = m - up[i - 1];j <= m;j++) f[i][m] = min(f[i][m],min(f[i-1][j],f[i][j]) + 1); for(int j = 1;j <= m - dw[i - 1];j++) f[i][j] = min(f[i][j],f[i-1][j + dw[i - 1]]); if(vis[i]) { for(int j = 1;j <= h[vis[i]].l;j++) f[i][j] = inf; for(int j = h[vis[i]].h;j <= m;j++) f[i][j] = inf; } int res = inf; for(int j = 1;j <= m;j++) res = min(f[i][j],res); if(res == inf) { cout << "0" << endl;int ans = 0; for(int j = 1;j < i;j++) ans += !!vis[j]; cout << ans << endl; return 0; } } int ans = inf; for(int i = 1;i <= m;i++) ans = min(ans,f[n + 1][i]); cout << "1\n" << ans << endl; return 0; }