您的位置:首页 > 其它

zoj 3469 Food Delivery 区间DP

2016-04-18 20:54 441 查看
Food Delivery
Time Limit: 2 Seconds     
Memory Limit: 65536 KB

When we are focusing on solving problems, we usually prefer to stay in front of computers rather than go out for lunch. At this time, we may call for food delivery.

Suppose there are N people living in a straight street that is just lies on an X-coordinate axis. The
ith person's coordinate is Xi meters. And in the street there is a take-out restaurant which has coordinates
X meters. One day at lunchtime, each person takes an order from the restaurant at the same time. As a worker in the restaurant, you need to start from the restaurant, send food to the
N people, and then come back to the restaurant. Your speed is V-1 meters per minute.

You know that the N people have different personal characters; therefore they have different feeling on the time their food arrives. Their feelings are measured by
Displeasure Index. At the beginning, the Displeasure Index for each person is 0. When waiting for the food, the
ith person will gain BiDispleasure Index per minute.

If one's Displeasure Index goes too high, he will not buy your food any more. So you need to keep the sum of all people's
Displeasure Index as low as possible in order to maximize your income. Your task is to find the minimal sum of
Displeasure Index.

Input

The input contains multiple test cases, separated with a blank line. Each case is started with three integers
N ( 1 <= N <= 1000 ), V ( V > 0), X (
X >= 0 ), then N lines followed. Each line contains two integers
Xi ( Xi >= 0 ), Bi (
Bi >= 0), which are described above.

You can safely assume that all numbers in the input and output will be less than 231 - 1.

Please process to the end-of-file.

Output

For each test case please output a single number, which is the minimal sum of
Displeasure Index. One test case per line.

Sample Input

5 1 0

1 1

2 2

3 3

4 4

5 5

Sample Output

55

  似乎大家都说这是一道很好的DP题,由于本菜没做几道DP,只能把这题描述成一道很绕的DP题。。。

  我们首先明确以下dp数组的含义。

  dp[i][j][k],表示在[i,j]区间内送饭的最小不满意度,k=0时表示最终停留在i点,k=1时表示最终停留在j点。

  现在我们知道了dp[i][j][k]所表示的状态了,那么怎么转移到这个状态上来呢?对于一个确定的状态dp[i][j][0],我们向前考虑一步,我们发现存在两个状态,dp[i+1][j][0]和dp[i+1][j][1],也就是说他可能从i+1这个点移动到i,也可能从j这个点移动到i。

  如果从i+1这个点移动到i花费了时间t,那么除了i等待了t,其它所有还没收到午餐的用户也都等待了t,因此要把他们的不满意度都加上,然后我们在两种情况中选一个较小的。

下面是状态转移方程:

            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));

            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));

要理解这个并不轻松,所以大家如果有任何疑问可以给我留言,或者加QQ1451574179,我会近最大努力予以解答。

   另外有一点要说明的,我们在转移方程中并没有使用时间来计算,而是用的路程,这得益于题目给出的速度v=V^(-1),我们知道s/v=t,即s×V=t,看出来了吧,我们可以不用每次都把时间算出来,只要将最后的结果乘以V即可。

/*********************
功能: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;
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));

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
.x=x;
p
.d=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);
}
return 0;
}
/**********************
输入:
5 1 0
1 1
2 2
3 3
4 4
5 5
输出
55
**********************/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息