题目描述:
Alibaba the famous character of our childhood stories would like to be immortal in order to keep
bringing happiness to children. In order to rich this status he needs to prove that he is still able to
do some unusual things. There are n treasures, (n ≤ 10000) each in a different place located along
a straight road. Each treasure has a time limit, after that it vanishes. Alibaba must take all the n
treasures, and he must do it quickly. So he needs to figure out the order in which he should take the
treasures before their deadlines starting from the most favorable position. Alibaba has the list of places
and 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 he
can 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 - deadline
in 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 output
on a separate line. The solution is represented by the smallest time by which Alibaba can take all the
treasures before they vanish. If this is not possible then the output is ‘No solution’.
Sample Input
5
1 3
3 1
5 8
8 19
10 15
5
1 5
2 1
3 4
4 2
5 3
Sample Output
11
No solution
题意:
在一条直线上有n(n<=10000)个点有宝藏,其中第i个点的坐标是xi(每个点的坐标都是整数),且每个宝藏在di秒之后都会消失,Alibaba可以在任何一个点出发,移动一个单位需要一个单位的时间,求访问完所有点的最短时间,无解则输出No solution。输入按照坐标递增顺序。取宝藏时间忽略不计。
分析:
区间dp,根据贪心在区间[i,j]内取完宝藏后必在i点或则j点,用数组dp[i][j][0]表示拿完区间内的所有宝藏,且最后位于i,用dp[i][j][1]表示拿完区间间的所有宝藏且最后位于j。则状态转移方程为:
dp[i][j][0]=min(dp[i+1][j][0]+a[i+1]-a[i],dp[i+1][j][1]+a[j]-a[i]);
dp[i][j][1]=min(dp[i][j-1][0]+a[j]-a[i],dp[i][j-1][1]+a[j]-a[j-1]);
判断是否有解的方法:更新完dp[i][j][0]后比较其与di的大小,如果比di大则无解,赋值inf,同理处理dp[i][j][1]。
ac代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=10005;
const int inf=0x3f3f3f3f;
int a[maxn],v[maxn],dp[maxn][maxn][2];
int main()
{
//freopen("in.txt","r",stdin);
int n;
while(~scanf("%d",&n))
{
memset(a,0,sizeof(a));
memset(v,0,sizeof(v));
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i],&v[i]);
for(int i=1;i<=n;i++)
dp[i][i][0]=dp[i][i][1]=0;
for(int i=n-1;i>0;i--)
{
for(int j=i+1;j<=n;j++)
{
dp[i][j][0]=min(dp[i+1][j][0]+a[i+1]-a[i],dp[i+1][j][1]+a[j]-a[i]);
if(dp[i][j][0]>=v[i])
dp[i][j][0]=inf;
dp[i][j][1]=min(dp[i][j-1][0]+a[j]-a[i],dp[i][j-1][1]+a[j]-a[j-1]);
if(dp[i][j][1]>=v[j])
dp[i][j][1]=inf;
}
}
int ans=min(dp[1][n][0],dp[1][n][1]);
if(ans>=inf)
printf("No solution\n");
else
printf("%d\n",ans);
}
}