定义为跳跃到的最小代价
那么枚举每个座标和每个座标
每个状态都是前一个位置跳跃若干次上来的,所以可以写出很暴力的代码
#include <bits/stdc++.h> using namespace std; const int maxn=10009; int n,m,k,id=1; int x[maxn],y[maxn]; struct p{ int x,l,r; bool operator < (const p&tmp ) const{ return x<tmp.x; } }a[maxn]; int dp[10009][1009]; int main() { cin >> n >> m >> k; for(int i=0;i<n;i++) cin >> x[i] >> y[i]; for(int i=1;i<=k;i++) cin >> a[i].x >> a[i].l >> a[i].r; sort(a+1,a+1+k); memset(dp,20,sizeof(dp)); int inf=dp[0][0]; for(int i=1;i<=m;i++) dp[0][i]=0; for(int i=1;i<=n;i++) { int l=1,r=m; if( a[id].x==i ) l=a[id].l+1,r=a[id].r-1,id++; l = max( l,1 ); for(int j=l;j<=r;j++)//枚举高度 { dp[i][j] = min( dp[i][j],dp[i-1][j+y[i-1]] ); if( j==m ) { for(int q=1;q<=m;q++) { int r = (m-q)/x[i-1]; if( (m-q)%x[i-1]||q==m ) r++; dp[i][j]=min( dp[i][j],dp[i-1][q]+r ); } continue; } for(int q=1;j>=q*x[i-1];q++) dp[i][j]=min( dp[i][j],dp[i-1][j-q*x[i-1]]+q ); } } int ans = inf; for(int i=1;i<=m;i++) ans = min( ans,dp[n][i] ); if( ans==inf ) { int da=0; for(int i=1;i<=k;i++) { for(int j=1;j<=m;j++) if( dp[a[i].x][j]!=inf ) { da++;break; } } cout << 0 << endl << da; } else cout << 1 << endl << ans; }
但是我们发现转移的过程非常浪费
比如是从跳跃若干次到达的,这样枚举复杂度太高了
可以由转移而来,因为之前已经计算过
可以由转移而来,就是从上一层转移过来
所以这样就优化了复杂度
#include <bits/stdc++.h> using namespace std; const int maxn=10009; int n,m,k,id=1; int x[maxn],y[maxn]; struct p{ int x,l,r; bool operator < (const p&tmp ) const{ return x<tmp.x; } }a[maxn]; int dp[10009][2009]; int main() { cin >> n >> m >> k; for(int i=0;i<n;i++) cin >> x[i] >> y[i]; for(int i=1;i<=k;i++) cin >> a[i].x >> a[i].l >> a[i].r; sort(a+1,a+1+k); memset(dp,20,sizeof(dp)); int inf=dp[0][0]; for(int i=1;i<=m;i++) dp[0][i]=0; for(int i=1;i<=n;i++) { int l=1,r=m; if( a[id].x==i ) l=a[id].l+1,r=a[id].r-1,id++; l = max( l,1 ); for(int j=1;j<=r;j++) { if( j==m ) continue; if( j-x[i-1]>=1 ) dp[i][j]=min( dp[i][j],min( dp[i-1][j-x[i-1]],dp[i][j-x[i-1]])+1 ); } if( r>=m ) { for(int j=m-x[i-1];j<=m;j++) if( j>=1 ) dp[i][m]=min( dp[i][m],min( dp[i-1][j],dp[i][j])+1 ); } for(int j=l;j<=r;j++) dp[i][j] = min(dp[i][j],dp[i-1][j+y[i-1]]); for(int j=1;j<=l-1;j++) dp[i][j]=inf; } int ans = inf; for(int i=1;i<=m;i++) ans = min( ans,dp[n][i] ); if( ans==inf ) { int da=0; for(int i=1;i<=k;i++) { for(int j=1;j<=m;j++) if( dp[a[i].x][j]!=inf ) { da++;break; } } cout << 0 << endl << da; } else cout << 1 << endl << ans; }