题目:https://www.luogu.org/problemnew/show/P1941
dp。只是dp而已。作为自中午考试爆炸而阴郁的一下午一晚上中一点的慰藉。
滚动数组每次赋初值在这道题中变成了一种方便。处理障碍只需要将上一阶段对应位置赋成 INF 就行了。
注意降下来的那种情况得在完全背包运行完了之后再考虑。不然就可能同一阶段即下降又上升。
还有就是顶层可转移来的状态多些。全程都是不能触及到第0行的。
#include<iostream> #include<cstdio> #include<cstdlib> using namespace std; const long long INF=0x7fffffff; int n,m,k,x[10005],y[10005],uj[10005],dj[10005],p,h,l,cnt; bool zh[10005]; long long d[2][1005],ans=INF; void pan(int i) { bool flag=0; for(int j=0;j<=m;j++) if(d[i%2][j]!=INF) { flag=1;break; } if(flag)return; printf("0 %d",cnt); exit(0); } int main() { scanf("%d%d%d",&n,&m,&k); for(int i=0;i<n;i++)scanf("%d%d",&x[i],&y[i]); for(int i=1;i<=k;i++) { scanf("%d%d%d",&p,&l,&h); zh[p]=1;dj[p]=l;uj[p]=h; } for(int i=1;i<=n;i++) { // printf("i=%d ",i); bool flag=0; for(int j=0;j<=m;j++)d[i%2][j]=INF; if(zh[i-1]) { flag=1; for(int j=0;j<=dj[i-1];j++)d[(i-1)%2][j]=INF; for(int j=uj[i-1];j<=m;j++)d[(i-1)%2][j]=INF; } for(int j=x[i-1]+1;j<=m;j++) { d[i%2][j]=min(d[i%2][j],min(d[(i-1)%2][j-x[i-1]]+1,d[i%2][j-x[i-1]]+1)); // printf(" d[%d]=%d ",j,d[i%2][j]); } for(int j=m-x[i-1]+1;j<=m;j++) { d[i%2][m]=min(d[i%2][m],min(d[(i-1)%2][j]+1,d[i%2][j]+1)); // printf(" d[%d]=%d ",j,d[i%2][j]); } int ll=m-y[i-1]; for(int j=1;j<=ll;j++) { d[i%2][j]=min(d[i%2][j],d[(i-1)%2][j+y[i-1]]); // printf(" d[%d]=%d ",j,d[i%2][j]); } pan(i); if(flag)cnt++; } for(int i=1;i<=m;i++) ans=min(ans,d[n%2][i]); printf("1 %lld",ans); return 0; }