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 }
View Code

 

posted @ 2020-05-11 15:29  古比  阅读(125)  评论(0编辑  收藏  举报