C 张老师的旅行(区间dp)
题:https://ac.nowcoder.com/acm/contest/5477/C
分析:最少时间能走完的点一定是连线的[l,r],又n<=1000所以考虑区间dp,设dp[i][j][k],0<=k<=1,当k==0时代表最少时间跑完区间[i,j]且终点在l时的最少时间,k==1时则是终点在r的情况;
转移方程一般都是[i+1,j]->[i,j]和[i,j-1]>>[i,j]。
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define pb push_back const int inf=0x3f3f3f3f; const ll INF=1e18; const int mod=998244353; ll ksm(ll x,ll y){ ll t=1; while(y){ if(y&1) t=(t*x)%mod; x=(x*x)%mod; y>>=1; } return t; } void pn(){ cout<<"No"<<'\n'; } void py(){ cout<<"Yes"<<'\n'; } const int M=1e3+5; int dp[M][M][2],a[M],t[M]; char s[M]; int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) scanf("%d",&t[i]); for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) dp[i][j][0]=dp[i][j][1]=inf; for(int i=1;i<=n;i++) if(t[i]==0) dp[i][i][0]=dp[i][i][1]=0; int tmp; for(int len=2;len<=n;len++) for(int i=1;i+len-1<=n;i++){ int j=i+len-1; ///[i+1,j]->[i,j] tmp=dp[i+1][j][0]+abs(a[i+1]-a[i]); if (t[i]>=tmp) dp[i][j][0]=min(dp[i][j][0],tmp); tmp=dp[i+1][j][1]+abs(a[j]-a[i]); if (t[i]>=tmp) dp[i][j][0]=min(dp[i][j][0],tmp); tmp=dp[i][j-1][1]+abs(a[j]-a[j-1]); ///[i,j-1]>>[i,j] if (t[j]>=tmp) dp[i][j][1]=min(dp[i][j][1],tmp); tmp=dp[i][j-1][0]+abs(a[j]-a[i]); if (t[j]>=tmp) dp[i][j][1]=min(dp[i][j][1],tmp); } int ans=min(dp[1][n][0],dp[1][n][1]); if(ans>=inf) ans=-1; printf("%d\n",ans); return 0; }