题目大意
排成一条直线的n个点,要从一个点走完所有点再回到原点,其中第i个点位于数轴上的位置x[i]。如果从i跳到j,首先要花费时间|x[j]-x[i]|。假如i
解题思路
设f[i][j][k]为到第i个点,有j条边连出去,k条边连进来的最小花费。
1)
![这里写图片描述](https://img-blog.csdn.net/20160906154648890)
f[i][j][k]=f[i-1][j+1][k+1]+a[i]+c[i]+x[i]*2;
2)
![这里写图片描述](https://img-blog.csdn.net/20160906154748094)
f[i][j][k]=f[i-1][j][k]+a[i]+d[i];
3)
![这里写图片描述](https://img-blog.csdn.net/20160906154834765)
f[i][j][k]=f[i-1][j][k]+b[i]+c[i];
4)
![这里写图片描述](https://img-blog.csdn.net/20160906154929907)
f[i][j][k]=f[i-1][j-1][k-1]+b[i]+d[i]-x[i]*2;
可以发现j==k,因此省去k。注意第2,3,4种情况j!=0。
code
using namespace std;
int const maxn=5000;
LL n,X[maxn+10],a[maxn+10],b[maxn+10],c[maxn+10],d[maxn+10],f[maxn+10][maxn+10];
int main(){
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%lld",&n);LL inf=1ll*2147483647*214748;
fo(i,1,n)scanf("%lld",&X[i]);
fo(i,1,n)scanf("%lld",&a[i]);
fo(i,1,n)scanf("%lld",&b[i]);
fo(i,1,n)scanf("%lld",&c[i]);
fo(i,1,n)scanf("%lld",&d[i]);
fo(i,0,n)fo(j,0,n)f[i][j]=-inf;
f[1][1]=b[1]+d[1]-X[1]*2;
fo(i,1,n-1)
fo(j,0,i)if(f[i][j]!=-inf){
if(j)f[i+1][j-1]=max(f[i+1][j-1],f[i][j]+a[i+1]+c[i+1]+X[i+1]*2);
if(j)f[i+1][j]=max(f[i+1][j],max(f[i][j]+a[i+1]+d[i+1],f[i][j]+c[i+1]+b[i+1]));
f[i+1][j+1]=max(f[i+1][j+1],f[i][j]+d[i+1]+b[i+1]-X[i+1]*2);
}
printf("%lld",f[n][0]);
return 0;
}