大意:直线上有n个点,其中第i个点的坐标为xi,且它会在di秒后消失。Alibaba可以从直线任意位置出发,求访问玩所有点的最短时间,无解输出No solution.
思路:对所有点按照坐标从小到大排序,发现访问过的点一定是一个连续区间,用d[i][j][0]表示访问了区间(i, j),Alibaba在左端点,d[i][j][1]表示访问了区间(i, j),Alibaba在右端点。
// Created by Chenhongwei in 2015.
// Copyright (c) 2015 Chenhongwei. All rights reserved.
#include"iostream"
#include"cstdio"
#include"cstdlib"
#include"cstring"
#include"climits"
#include"queue"
#include"cmath"
#include"map"
#include"set"
#include"stack"
#include"vector"
#include"sstream"
#include"algorithm"
using namespace std;
typedef long long ll;
const int inf=1e8;
struct data
{
int p,t;
}a[10010];
int n;
int dp[10010][10010][2];
int main()
{
//ios::sync_with_stdio(false);
// freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].p,&a[i].t);
dp[i][i][0]=0;
dp[i][i][1]=0;
}
for(int i=n;i>=0;i--)
for(int j=i+1;j<=n;j++)
{
dp[i][j][0]=dp[i][j][1]=inf;
int tmp=min(dp[i+1][j][0]+a[i+1].p-a[i].p,dp[i+1][j][1]+a[j].p-a[i].p);
if(tmp<a[i].t)
dp[i][j][0]=min(tmp,dp[i][j][0]);
tmp=min(dp[i][j-1][0]+a[j].p-a[i].p,dp[i][j-1][1]+a[j].p-a[j-1].p);
if(tmp<a[j].t)
dp[i][j][1]=min(tmp,dp[i][j][1]);
}
int ans=min(dp[1][n][0],dp[1][n][1]);
if(ans<inf)
cout<<ans<<endl;
else
cout<<"No solution"<<endl;
}
return 0;
}