UVA1632_Alibaba

版权声明:欢迎转载,转载时请注明出处 https://blog.csdn.net/xfzero/article/details/48318561

题目链接

大致题意:直线上面有n个点,第i个点坐标为xi,它会在di时间消失,你可以选择从任何位置出发,求访问完所有点的最短时间,无解输出no solution

思路:这有一个难点就是,不知道状态该怎么转移,其实仔细想想之后会发现我们在走的时候一定是一个区间的慢慢扩大,假设第k次之前做的都是完整区间,那么k+1次只能走这个区间右端+1坐在左端-1的这两个点,因为走的时候必须路过

这样的话,状态转移就明确了,他只能从上一个区间左端和右端转移过来.不过问题又来了,区间大小不确定.其实区间大小可以状态转移过去,k+1大小的区间必然是由k大小的区间转移过来

所以用dp[i][j][0]表示左端,dp[i][j][1]表示区间右端,其中i表示当前区间大小,j表示位置,下面是我优化了内存

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include<stack>
#include<map>
#include<queue>
#include<vector>
using namespace std;
const int maxn = 1e4+10;
const int INF = 0x3f3f3f3f;
int p[maxn],t[maxn],dp[2][maxn][2],n,ans;
int main(){
 while(cin>>n){
    for(int i=1;i<=n;i++) cin>>p[i]>>t[i];
    for(int i=1;i<=n;i++) dp[0][i][0]=dp[0][i][1]=0;
    int x,nx=0;
    for(int i=1;i<n;i++){
        x=nx;nx^=1;
        for(int j=1;j<=n-i;j++){
            //0->left 1->right

            dp[nx][j][0]=min(dp[x][j+1][0]+p[j+1]-p[j],dp[x][j+1][1]+p[j+i]-p[j]);
            dp[nx][j][1]=min(dp[x][j][0]+p[j+i]-p[j],dp[x][j][1]+p[i+j]-p[i+j-1]);
            if(dp[nx][j][0]>=t[j]) dp[nx][j][0] = INF;
            if(dp[nx][j][1]>=t[i+j]) dp[nx][j][1] = INF;
        }
    }
    ans = min(dp[nx][1][0],dp[nx][1][1]);
    if(ans>=INF) cout<<"No solution\n";
    else cout<<ans<<"\n";

 }
    return 0;
}


阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页