zoukankan      html  css  js  c++  java
  • UVA-1632 Alibaba (区间DP+滚动数组)

    题目大意:在一条直线上有n件珠宝,已知每件珠宝的位置,并且第 i 件珠宝在 ti 时刻就消失,问能否将所有的珠宝收集起来?如果能,求出最短时间。搜集能瞬间完成。

    题目分析:区间DP。dp(i,j,0)表示搜集区间(i,j)并且停留在左端所需的最短时间,dp(i,j,1)表示搜集区间(i,j)并且停留在右端所需的最短时间。状态转移方程为

    dp(i,j,0)=min(dp(i+1,j,0)+t(i+1)-t(i),dp(i+1,j1,)+t(j)-t(i)),dp(i,j,1)=min(dp(i,j-1,0)+t(j)-t(i),dp(i,j-1,1)+t(j)-t(j-1))。

    这道题的数据规模比较大,可以用滚动数组优化空间复杂度。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    
    int dp[2][10005][2];
    int x[10005],t[10005],n;
    
    const int INF=0x7fffffff;
    
    int main()
    {
        while(~scanf("%d",&n))
        {
            for(int i=0;i<n;++i){
                scanf("%d%d",x+i,t+i);
                dp[1][i][0]=dp[1][i][1]=dp[0][i][0]=dp[0][i][1]=(t[i]>0)?0:INF;
            }
    
            for(int i=n-2;i>=0;--i){
                for(int j=i+1;j<n;++j){
                    dp[i&1][j][0]=dp[i&1][j][1]=INF;
                    if(dp[(i&1)^1][j][0]!=INF&&dp[(i&1)^1][j][0]+x[i+1]-x[i]<t[i])
                        dp[i&1][j][0]=min(dp[i&1][j][0],dp[(i&1)^1][j][0]+x[i+1]-x[i]);
                    if(dp[(i&1)^1][j][1]!=INF&&dp[(i&1)^1][j][1]+x[j]-x[i]<t[i])
                        dp[i&1][j][0]=min(dp[i&1][j][0],dp[(i&1)^1][j][1]+x[j]-x[i]);
                    if(dp[i&1][j-1][0]!=INF&&dp[i&1][j-1][0]+x[j]-x[i]<t[j])
                        dp[i&1][j][1]=min(dp[i&1][j][1],dp[i&1][j-1][0]+x[j]-x[i]);
                    if(dp[i&1][j-1][1]!=INF&&dp[i&1][j-1][1]+x[j]-x[j-1]<t[j])
                        dp[i&1][j][1]=min(dp[i&1][j][1],dp[i&1][j-1][1]+x[j]-x[j-1]);
                }
            }
            if(dp[0][n-1][1]==INF&&dp[0][n-1][0]==INF) printf("No solution
    ");
            else printf("%d
    ",min(dp[0][n-1][0],dp[0][n-1][1]));
        }
        return 0;
    }
    

      

      

    下面这个是不加滚动数组的:

    # include<iostream>
    # include<cstdio>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    
    int dp[10005][10005][2];
    int x[10005],t[10005],n;
    
    const int INF=1000000000;
    
    int main()
    {
        while(~scanf("%d",&n))
        {
            for(int i=0;i<n;++i)
                scanf("%d%d",x+i,t+i),dp[i][i][0]=dp[i][i][1]=0;
    
            for(int i=n-2;i>=0;--i){
                for(int j=i+1;j<n;++j){
                    dp[i][j][0]=min(dp[i+1][j][0]+x[i+1]-x[i],dp[i+1][j][1]+x[j]-x[i]);
                    if(dp[i][j][0]>=t[i]) dp[i][j][0]=INF;
                    dp[i][j][1]=min(dp[i][j-1][0]+x[j]-x[i],dp[i][j-1][1]+x[j]-x[j-1]);
                    if(dp[i][j][1]>=t[j]) dp[i][j][1]=INF;
                }
            }
            if(dp[0][n-1][1]==INF&&dp[0][n-1][0]==INF) printf("No solution
    ");
            else printf("%d
    ",min(dp[0][n-1][0],dp[0][n-1][1]));
        }
        return 0;
    }
    

      

  • 相关阅读:
    cmd 窗口中运行 Java 程序
    局部变量保证线程安全
    AQS源码详细解读
    理解 Java 内存模型的因果性约束
    高性能Java序列化框架Fse发布
    心跳与超时:高并发高性能的时间轮超时器
    支持内部晋升的无锁并发优先级线程池
    最终一致性:BASE论文笔记
    Activiti架构分析及源码详解
    理解OAuth2
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5200518.html
Copyright © 2011-2022 走看看