分析:
给出n个正整数表示x轴上坐标,给出起点s和终点e,要求从s出发遍历其他点到达终点e的花费最小,花费计算:
从点i到点j
|xi - xj| + ci + bj seconds if j < i.
|xi - xj| + di + aj seconds otherwise (j > i).题解:
可以理解为一条从s到e的链,不断向其中添加点使得整条链的花费最小。AC代码:
/*************************************************************************
> File Name: test.cpp
> Author: Akira
> Mail: qaq.febr2.qaq@gmail.com
************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <set>
#include <list>
#include <ctime>
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) ((a)*(a))
using namespace std;
#define MaxN 5005
#define MaxM MaxN*10
#define INF 1e18
#define bug cout<<88888888<<endl;
LL n,s,e;
LL Map[MaxN];
LL a[MaxN], b[MaxN], c[MaxN], d[MaxN];
LL Next[MaxN];
LL ans;
LL dis(LL i, LL j) //计算i-j花费
{
return abs(Map[i]-Map[j]) + ( Map[j]<Map[i] ? c[i]+b[j] : d[i]+a[j] );
}
void solve()
{
ans = 0;
Next[s] = e;
ans += dis(s,e);
for(LL i=1;i<=n;i++) //遍历所有点加入
{
if(i==s||i==e)continue;
LL Min=INF;
LL index;
for(LL j=s; j!=e; j=Next[j]) //从头到尾遍历当前链中的所有点
{
LL tmp = dis(j,i) + dis(i, Next[j]) - dis(j,Next[j]); //计算添加新店并拆开旧边的花费
if(tmp<Min) Min = tmp, index = j; //记录下当前点最小花费的位置
}
ans += Min;
Next[i] = Next[index]; //加入点
Next[index] = i;
}
}
int main()
{
while(~scanf("%I64d%I64d%I64d", &n, &s, &e))
{
CLR(Next);
for(LL i=1;i<=n;i++)
scanf("%I64d", &Map[i]);
for(LL i=1;i<=n;i++)
scanf("%I64d", &a[i]);
for(LL i=1;i<=n;i++)
scanf("%I64d", &b[i]);
for(LL i=1;i<=n;i++)
scanf("%I64d", &c[i]);
for(LL i=1;i<=n;i++)
scanf("%I64d", &d[i]);
solve();
cout << ans << endl;
}
//system("pause");
}