zoukankan      html  css  js  c++  java
  • 【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
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    webpack
    线程和同步
    C#高性能TCP服务
    平台架构实践
    异步
    net MVC 的八个扩展点
    Python计算&绘图——曲线拟合问题(转)
    最小二乘法多项式曲线拟合原理与实现(转)
    Apache Commons Math3学习笔记(2)
    最小二乘法拟合java实现源程序(转)
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626162.html
Copyright © 2011-2022 走看看