【Uva 1632】Alibaba

Link:

Description

直线上有n(n≤10000)个点,其中第i个点的坐标是xi,且它会在di秒之后消失。Alibaba 可以从任意位置出发,求访问完所有点的最短时间。无解输出No solution。
恰好在di秒到的话,不算到

Solution

访问到点的时候,因为是秒取点的;
所以最后的答案肯定是一段区间;
按照之前区间动规的思路;
假设当前到了[l..r]这段区间的最左边/最右边;
然后枚举下一个要到哪里(l-1或r+1);
但是这样定义状态是不可行的;
因为要开一个1W*1W的数组;
于是我们按照区间的长度作为状态;
可以发现之前定义的状态;
可以按照区间的长度来递推;
可以发现都是从长度为l的区间递推到长度为l+1的区间
可以枚举一下区间的左端点,然后做一下顺推;
因为只从l递推到l+1;
则可以用滚动数组了;
只需定义f[2][1e4][2]即可;
第一维代表区间长度,(上一个长度和当前长度),第二维代表区间的左端点,第三维表示在这个区间的左端还是右端;
最后答案在f[n&1][1][0]和f[n&1][1][1]里面找即可;
刚好在b[i]的时候到达a[i]不算到达

NumberOf WA

1

Reviw

发现只是由前一个状态递推到后一个状态的话;
都能用滚动数组优化空间;
以后都把int定义为long long :)

Code

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N =  1e4;
const int INF = 0x3f3f3f3f;

int n,a[N+10],b[N+10],f[2][N+10][2];

main(){
    //freopen("F:\\rush.txt","r",stdin);
    while (~scanf("%lld",&n)){
        for (int i = 1;i <= n;i++)
            scanf("%lld%lld",&a[i],&b[i]);
        for (int i = 1;i <= n;i++){
            f[1][i][0] = f[1][i][1] = (b[i]>0?0:INF);
        }
        for (int i = 1;i <= n-1;i++){
            int cur = i&1;
            memset(f[cur^1],INF,sizeof f[cur^1]);
            for (int j = 1;j <= n-i+1;j++){
                if (f[cur][j][0]<INF){
                    // l = j,r = j+i-1,0
                    // l = j-1,r = j-1+i+1-1 = j+i-1
                    if (j >= 2){
                        f[cur^1][j-1][0] = min(f[cur^1][j-1][0],f[cur][j][0]+a[j]-a[j-1]);
                        if (f[cur^1][j-1][0]>=b[j-1])
                            f[cur^1][j-1][0] = INF;
                    }
                    //l = j,r = j+i+1-1 = j+i
                    if (j+i<=n){
                        f[cur^1][j][1] = min(f[cur^1][j][1],f[cur][j][0]+a[j+i]-a[j]);
                        if (f[cur^1][j][1] >= b[j+i])
                            f[cur^1][j][1] = INF;
                    }
                }
                if (f[cur][j][1]<INF){
                    // l = j,r = j+i-1,1
                    // l = j-1,r = j-1+i+1-1 = j+i-1
                    if (j >= 2){
                        f[cur^1][j-1][0] = min(f[cur^1][j-1][0],f[cur][j][1]+a[j+i-1]-a[j-1]);
                        if (f[cur^1][j-1][0]>=b[j-1])
                            f[cur^1][j-1][0] = INF;
                    }
                    //l = j,r = j+i+1-1 = j+i
                    if (j+i<=n){
                        f[cur^1][j][1] = min(f[cur^1][j][1],f[cur][j][1]+a[j+i]-a[j+i-1]);
                        if (f[cur^1][j][1] >= b[j+i])
                            f[cur^1][j][1] = INF;
                    }
                }
            }
        }
        int ans = min(f[n&1][1][0],f[n&1][1][1]);
        if (ans>=INF)
            puts("No solution");
        else
            printf("%lld\n",ans);
    }
    return 0;
}
posted @ 2017-10-04 18:44  AWCXV  阅读(93)  评论(0编辑  收藏  举报