题目链接:
题目大意:在X轴上有一个餐厅,以及有n个点要送外卖。餐厅坐标为x,工人的速度为V秒1米,。给出n的点的x坐标和参数v,外卖没送到,客户就会不愉快,每一分钟的不愉快指数增加v[i]。问怎么样的送货策略,使得所有客户的总不愉悦指数和最小。
思路:我们把n个要送的外卖点和店的位置进行排序。
i为店的位置,那么他下一次要么去i-1,或者i+1。
假如下一次去了i-1。接下来:
要么去i-2,或者i+1。
那么用dp[L][R][0/1]分别表示把区间[L, R]的人外卖送完,用的最小时间。
那么如图:
dp[L][R][0]只能由dp[L+1][R][0]或者dp[L+1][R][1]转移而来。
同理:dp[L][R][1]只能由dp[L][R-1][0]或者dp[L][R-1][1]转移而来。
L和R开始=店的起始位置,并且L只能–,R只能++。
还有我们要把这个dp[L][R][0]送餐过程,[1, L]和[R+1, n]等待是愤怒值加在dp[L][R][0]上。那么可以消除时间对无后效性的影响。这个性质在之前的博客也有体现。
#include <bits/stdc++.h>
#define LL long long
using namespace std;
struct node
{
LL x;
LL v;
}a[1005];
LL s[1005];
LL dp[1005][1005][2];
int cmp(node &a, node &b)
{
return a.x<b.x;
}
LL sum(int L, int R)
{
return s[R]-s[L-1];
}
LL dfs(int n, int p)
{
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
dp[i][j][0]=dp[i][j][1]=1ll*10000000000;
}
int pos;
for(int i=1;i<=n;i++)
{
if(a[i].x==p)
{
pos=i;
}
}
dp[pos][pos][0]=dp[pos][pos][1]=0;
for(int L=pos; L>=1; L--)
{
for(int R=pos; R<=n; R++)
{
if(L==R)
{
continue;
}
dp[L][R][0]=min(1ll*10000000000, dp[L+1][R][0]+abs(a[L+1].x-a[L].x)*(sum(1,L)+sum(R+1,n)));
dp[L][R][0]=min(dp[L][R][0], dp[L+1][R][1]+abs(a[R].x-a[L].x)*(sum(1, L)+sum(R+1, n)));
dp[L][R][1]=min(1ll*10000000000, dp[L][R-1][1]+abs(a[R].x-a[R-1].x)*(sum(1, L-1)+sum(R, n)));
dp[L][R][1]=min(dp[L][R][1], dp[L][R-1][0]+abs(a[R].x-a[L].x)*(sum(1, L-1)+sum(R, n)));
}
}
return min(dp[1][n][0], dp[1][n][1]);
}
int main()
{
int n, v, p;
while(~scanf("%d%d%d",&n,&v,&p))
{
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&a[i].x,&a[i].v);
}
a[n+1].x=p, a[n+1].v=0;
sort(a+1, a+n+2, cmp);
s[0]=0;
for(int i=1;i<=n+1;i++)
{
s[i]=s[i-1]+a[i].v;
}
cout<<dfs(n+1, p)*v<<endl;
}
return 0;
}