这道题是一道隐藏的比较深的DP(我太蒟蒻了!)
设f[i][j]表示到第i列时高度为j的最少步数是多少;
求上升时的方案就是一个完全背包!,求下降时的方案就是一个01背包;
然后处理边界就能A掉;
#include <bits/stdc++.h> using namespace std; int n,m,k; int up[100010],down[100010]; int low[100010],top[100010],bo[100010]; int f[10010][2010]; int main() { cin>>n>>m>>k; for(register int i=1;i<=n;i++){ scanf("%d%d",&up[i],&down[i]); low[i]=1; top[i]=m; } for(register int i=1;i<=k;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); bo[a]=1; low[a]=b+1; top[a]=c-1; } memset(f,0x3f,sizeof(f)); for(register int i=1;i<=m;i++){ f[0][i]=0; } for(register int i=1;i<=n;i++){ for(register int j=up[i]+1;j<=m+up[i];j++){ f[i][j]=min(f[i][j-up[i]]+1,f[i-1][j-up[i]]+1); } for(register int j=m+1;j<=m+up[i];j++){ f[i][m]=min(f[i][m],f[i][j]); } for(register int j=1;j<=m-down[i];j++){ f[i][j]=min(f[i-1][j+down[i]],f[i][j]); } for(register int j=1;j<low[i];j++){ f[i][j]=f[0][0]; } for(register int j=top[i]+1;j<=m;j++){ f[i][j]=f[0][0]; } } int ans=f[0][0]; for(register int i=1;i<=m;i++){ ans=min(ans,f[n][i]); } if(ans<f[0][0]){ cout<<"1"<<endl; cout<<ans<<endl; } else{ cout<<"0"<<endl; int i,j; for(i=n;i>=1;i--){ for(j=1;j<=m;j++){ if(f[i][j]<f[0][0]){ break; } } if(j<=m){ break; } } ans=0; for(int j=1;j<=i;j++){ if(bo[j]) ans++; } cout<<ans; } }