有一家快餐店送外卖,现在同时有n个家庭打进电话订购,送货员得以V-1的速度一家一家的运送,但是每一个家庭都有一个不开心的值,每分钟都会增加一倍,值达到一定程度,该家庭将不会再订购外卖了,现在为了以后有更多的家庭订购,要将外卖送到的情况下使得所有用户的不开心值总和达到最小
先将各个点按坐标排序,餐厅也算一个点;从小到大排序;
状态转移方程:
从餐厅向两边遍历:i为左,j为右,dp[i][j][0]代表从i->j的区间,且最终停在左边;
dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][0]+(delay+p[i].d)*(p[i+1].x-p[i].x));
........i...i+1...reataurant......j-1...j
(delay+p[i].d)代表总的愤怒值,(p[i+1].x-p[i].x))代表两点间距离即i+1->i;
下面同上;
dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][1]+(delay+p[i].d)*(p[j].x-p[i].x));
//愤怒总值乘上两点距离;在主函数中乘上V即可;因为愤怒值*t为所求,但是s*V=t;题目中的V为速度的倒数
dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][0]+(delay+p[j].d)*(p[j].x-p[i].x));
dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][1]+(delay+p[j].d)*(p[j].x-p[j-1].x));
/*********************
功能:x轴上有n个位置,每个位置有一个随时间增长的参数,要求从某个点开始,经过所有的点,并且使所有点的参数之和最小
参数:每个点的位置以及这个点的参数
返回值:最小的参数和
参数和不超过INF,最多maxn个点
*********************/
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define maxn 1010
#define INF 1100000000
using namespace std;
struct P
{
int x;
int d;
};
P p[maxn];
int dp[maxn][maxn][2];
int sum[maxn];
bool cmp(P a,P b)
{
return a.x<b.x;
}
int get_delay(int i,int j)
{
if(i>j)
return 0;
else
return sum[j]-sum[i-1];//返回两位置之间愤怒总值
}
int solve(int n,int X)
{
int res,delay;
int i,j;
for(i=0;i<n;i++)
if(p[i].x==X)
{
res=i;
break;//找到餐厅位置,从餐厅向左右两边遍历;
}
for(i=0;i<n;i++)
for(j=0;j<n;j++)
dp[i][j][0]=dp[i][j][1]=INF;//;初始化都为很大
dp[res][res][0]=dp[res][res][1]=0;//餐厅默认为0
for(i=res;i>=0;i--)
{
for(j=res;j<n;j++)
{//从餐厅向左右两边遍历;
if(i==j)
continue;
delay=get_delay(0,i-1)+get_delay(j+1,n-1);//计算两点以外的愤怒总值
dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][0]+(delay+p[i].d)*(p[i+1].x-p[i].x));
dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][1]+(delay+p[i].d)*(p[j].x-p[i].x));
//愤怒总值乘上两点距离;在主函数中乘上V即可;因为愤怒值*t为所求,但是s*V=t;题目中的V为速度的倒数
dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][0]+(delay+p[j].d)*(p[j].x-p[i].x));
dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][1]+(delay+p[j].d)*(p[j].x-p[j-1].x));
}
}
return min(dp[0][n-1][0],dp[0][n-1][1]);
}//遍历到两边;
int main()
{
int n,v,x;
int i;
while(~scanf("%d%d%d",&n,&v,&x))
{
for(i=0;i<n;i++)
scanf("%d%d",&p[i].x,&p[i].d);//输入每个点的坐标,及愤怒值
p[n].x=x;//默认第n个点为餐厅坐标
p[n].d=0;//愤怒值为0
n++;
sort(p,p+n,cmp);//按坐标排序;
memset(sum,0,sizeof(sum));
for(sum[0]=p[0].d,i=1;i<n;i++)
sum[i]=sum[i-1]+p[i].d;//计算坐标之间愤怒值;;;;;;
printf("%d\n",solve(n,x)*v);//最后乘上v
}
return 0;
}
/**********************
输入:
5 1 0
1 1
2 2
3 3
4 4
5 5
输出
55
**********************/