UVA-1632 Alibaba (區間DP)

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])

運用滾動數組可以大幅度減少空間複雜度。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章