ZOJ 3469-Food Delivery(区间dp经典题)

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. Theith person's coordinate is Xi meters. And in the street there is a take-out restaurant which has coordinatesX 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 theN 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 byDispleasure Index. At the beginning, the Displeasure Index for each person is 0. When waiting for the food, theith person will gain Bi Displeasure 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'sDispleasure Index as low as possible in order to maximize your income. Your task is to find the minimal sum ofDispleasure Index.

Input

The input contains multiple test cases, separated with a blank line. Each case is started with three integersN ( 1 <= N <= 1000 ), V ( V > 0), X (X >= 0 ), then N lines followed. Each line contains two integersXi ( 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题。第一次写,以新手角度表达一下思路。

题目要求累计焦虑度最低,为了使最多的人满意,应以最优方法运送外卖。而以餐馆为中心时,无论向x轴负方向还是正方向运送,必然选择离餐馆最近的某一客户。假设不选择相邻餐馆的客户运送,必然会途经该客户却不送餐,此处与最优解不符。

已知必须以餐馆为中心选取相邻客户点,而选取之后,依据此规则,必然继续选取相邻客户,因此可以用dp[i][j]表示i点到j点之间,用户的最低焦虑度,而假设以i,j之间开始送货,i,j之间客户送完之后,必然选取i-1或j+1。继而以dp[i][j][0]表示i,j区间以送达i时结束i,j之间送货,以dp[i][j][1】表示送达j时结束送货,那么dp方程就得到了。

            dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][0]+(delay+client[i].b)*(client[i+1].x-client[i].x));此处表示i,j区间的i点由i+1,j区间完成之后到达,且之前送货员恰好达到i+1点
            dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][1]+(delay+client[i].b)*(client[j].x-client[i].x));此处表示i,j区间的i点由i+1,j区间完成之后到达,且之前送货员恰好达到j点
            dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][0]+(delay+client[j].b)*(client[j].x-client[i].x));此处表示i,j区间的j点由i,j+1区间完成之后到达,且之前送货员恰好达到i点
            dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][1]+(delay+client[j].b)*(client[j].x-client[j-1].x));此处表示i,j区间的j点由i,j+1区间完成之后到达,且之前送货员恰好到达j-1点

#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
#define Max 200005

const int INF=0x3f3f3f3f;

int dp[1005][1005][2],sum[1005];
int n,v,x0;

struct a{
    int x,b;
}client[1005];

bool cmp(a x,a y){
    return x.x<y.x;
}

int getrest(int l,int r){
    if (r<l)
        return 0;
    return sum[r]-sum[l-1];
}

int solve(){
    int sign=0,delay;
    for (int i=1; i<=n; i++) {
        {if(client[i].x==x0) sign=i;}//此处应注意,由于主函数中以++n储存了餐馆信息,此处为了找到餐馆,不应第一次找到坐标相等的目标时即break退出循环,可能存在客户与餐馆x相同情况,而因为餐馆以++n存储,应是最后一个坐标相等的目标才为餐馆。也可倒序查找。
    }
    memset(dp, 0x3f, sizeof(dp));
    dp[sign][sign][0]=0;
    dp[sign][sign][1]=0;
    for (int i=sign; i>0; i--) {
        for (int j=sign; j<=n; j++) {
            if (i==j) {
                continue;
            }
            delay=getrest(1,i-1)+getrest(j+1,n);
            dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][0]+(delay+client[i].b)*(client[i+1].x-client[i].x));
            dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][1]+(delay+client[i].b)*(client[j].x-client[i].x));
            dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][0]+(delay+client[j].b)*(client[j].x-client[i].x));
            dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][1]+(delay+client[j].b)*(client[j].x-client[j-1].x));
        }
    }
    return min(dp[1][n][0], dp[1][n][1]);
}

int main(){
    while (cin>>n>>v>>x0) {
        memset(client, 0, sizeof(client));
        memset(sum, 0, sizeof(sum));
        for (int i=1; i<=n; i++) {
            cin>>client[i].x>>client[i].b;
        }
        client[++n].x=x0;client[n].b=0;
        sort(client+1, client+n+1, cmp);
        for (int i=1; i<=n; i++) {
            sum[i]=sum[i-1]+client[i].b;
        }
        cout<<solve()*v<<endl;
    }
    return 0;
}

你可能感兴趣的:(ZOJ 3469-Food Delivery(区间dp经典题))