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\n");
        else printf("%d\n",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\n");
        else printf("%d\n",min(dp[0][n-1][0],dp[0][n-1][1]));
    }
    return 0;
}

  

posted @ 2016-02-19 11:56  20143605  阅读(731)  评论(0编辑  收藏  举报