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

 

posted @ 2020-05-10 22:17  starve_to_death  阅读(186)  评论(0编辑  收藏  举报