C 张老师的旅行 区间DP
链接:https://ac.nowcoder.com/acm/contest/5477/C
题意:有n个直线排列的城市(可以看作是一条从原点到正半轴的x轴),a[i]表示i城市在这条x轴上的位置
有每一个城市所需到达的最低时间。
问:能否在规定时间内访问所有的城市,访问的最少时间为多少?
如果不能的话,输出-1
思路:按题目中给出,有一个起点。我们就得从这个起点向左右走来枚举出走到一个【L,R】内的最少时间
要枚举一个区间内的最优情况,即为区间DP
假定我们要走到一个区间为【L,R】,那么会有两种情况
一种是停在L,一种停在R,分别用0 ,1表示
于是,针对每一个情况如下:
停在0,即L,要想停在L,我们进行操作的区间即为【L+1,R】,有两种情况
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);
停在1,即R,也有两种情况,类似上面
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int M=1e3+5; 5 const int inf=0x3f3f3f3f; 6 int dp[M][M][2],a[M],t[M]; 7 // 0表示停在左边,1表示停在右边 8 int main(){ 9 int n; 10 scanf("%d",&n); 11 for(int i=1;i<=n;i++) 12 scanf("%d",&a[i]); 13 for(int i=1;i<=n;i++) 14 scanf("%d",&t[i]); 15 for(int i=0;i<=n;i++) 16 for(int j=0;j<=n;j++) 17 dp[i][j][0]=dp[i][j][1]=inf; 18 for(int i=1;i<=n;i++) 19 if(t[i]==0) 20 dp[i][i][0]=dp[i][i][1]=0; 21 int tmp; 22 for(int len=2;len<=n;len++) 23 for(int i=1;i+len-1<=n;i++){ 24 25 int j=i+len-1; 26 //[i+1,j]->[i,j] 27 tmp=dp[i+1][j][0]+abs(a[i+1]-a[i]); 28 if (t[i]>=tmp) dp[i][j][0]=min(dp[i][j][0],tmp); 29 tmp=dp[i+1][j][1]+abs(a[j]-a[i]); 30 if (t[i]>=tmp) dp[i][j][0]=min(dp[i][j][0],tmp); 31 //[i,j-1]>>[i,j] 32 tmp=dp[i][j-1][1]+abs(a[j]-a[j-1]); 33 if (t[j]>=tmp) dp[i][j][1]=min(dp[i][j][1],tmp); 34 tmp=dp[i][j-1][0]+abs(a[j]-a[i]); 35 if (t[j]>=tmp) dp[i][j][1]=min(dp[i][j][1],tmp); 36 } 37 int ans=min(dp[1][n][0],dp[1][n][1]); 38 if(ans>=inf) 39 ans=-1; 40 printf("%d\n",ans); 41 return 0; 42 }