UVA-1632 Alibaba (区间DP)

20 篇文章 0 订阅
2 篇文章 0 订阅

Alibaba the famous character of our childhood stories would like to be immortal in order to keepbringing happiness to children. In order to rich this status he needs to prove that he is still able todo some unusual things. There are n treasures, (n 10000) each in a different place located alonga straight road. Each treasure has a time limit, after that it vanishes. Alibaba must take all the ntreasures, and he must do it quickly. So he needs to figure out the order in which he should take thetreasures before their deadlines starting from the most favorable position. Alibaba has the list of placesand deadlines of the treasures. A place i is located at distance di from the leftmost end of the road.The time it takes to take a treasure is instantaneous. Alibaba must find the smallest time by which hecan take all the treasures.

Input

The program input is from a text file. Each data set in the file stands for a particular set of treasures.For each set of treasures the input contains the number of treasures, and the list of pairs place - deadlinein increasing order of the locations. White spaces can occur freely between the numbers in the input.The input data are correct. For each set of data the program prints the result to the standard outputon a separate line. The solution is represented by the smallest time by which Alibaba can take all thetreasures before they vanish. If this is not possible then the output is ‘No solution’.

Sample Input

5
133158
8 1910 15

51521344253

Sample Output

11
No solution

#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
#define INF 0x3f3f3f3f
const int N=10005;
const int mod=1e9+7;

int dis[N],t[N];
int d[2][N][2];

int main() {
    int n;
    while (cin>>n) {
        for (int i=1; i<=n; i++) {
            scanf("%d %d",&dis[i],&t[i]);
        }
        int cur=0,ans;
        memset(d, 0, sizeof(d));
        for (int i=n; i>=1; i--) {
            cur^=1;
            for (int j=i+1; j<=n; j++) {
                d[cur][j][0]=min(d[cur^1][j][0]+dis[i+1]-dis[i], d[cur^1][j][1]+dis[j]-dis[i]);
                if (d[cur][j][0]>=t[i]) d[cur][j][0]=INF;
                d[cur][j][1]=min(d[cur][j-1][0]+dis[j]-dis[i], d[cur][j-1][1]+dis[j]-dis[j-1]);
                if (d[cur][j][1]>=t[j]) d[cur][j][1]=INF;
            }
        }
        ans=min(d[cur][n][0], d[cur][n][1]);
        if (ans==INF) cout<<"No solution\n";
        else cout<<ans<<endl;
    }
    return 0;
}

直线上n个点,其中第i个点的坐标是xi,且它会在di秒时消失,问你从任意位置出发,访问完所有点的最短时间。无解输出No solution。

分析:

区间DP,之前好像做过这题但是印象不深,用d[i][j][0]表示从i-j区间拿完宝藏后处于第i个宝藏,d[i][j][1]表示拿完宝藏后处于第j个宝藏。

d[i][j][0]=min(d[i+1][j][0]+dis[i+1]-dis[i],d[i+1][j][1]+d[j]-dis[i])

d[i][j][1]=min(d[i]j-1][0]+dis[j]-dis[i],d[i][j-1][1]+dis[j]-dis[j-1])

运用滚动数组可以大幅度减少空间复杂度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值