*ZOJ3469.Food Delivery(三维区间DP)

题目链接:https://vjudge.net/problem/ZOJ-3469
题意:派送员从餐馆位置x出发,为n个人派送便当,速度是每v分钟走1个单位,每隔一分钟没有送到的人将会有b的不满意度,求最小的不满意度
解题思路:
可以知道每次走完一个区间,为了最优化,派送员一定是停在两端
dp[i][j][0]表示配送完i到j个人之后停在最左端i位置时最小的不满意度
dp[i][j][1]表示配送完i到j个人之后停在最右端i位置时最小的不满意度
将店铺位置x和不满意度0放入到n个需要派送的人之中,按位置从小到大进行排序,然后从排序后的店铺位置pos向两端进行dp讨论
转移方程:

             //不满意处理要包含除了i+1到j个人之外的所有人
             //处理左端点i时,它可以由上一个i+1点停在左右端情况得到
            dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][0]+(sum[n]-sum[j]+sum[i])*(p[i+1].x-p[i].x)); 
			dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][1]+(sum[n]-sum[j]+sum[i])*(p[j].x-p[i].x));
			//不满意处理要包含除了i到j-1个人之外的所有人
			//处理右端点j时,它可以由上一个j-1点停在左右端情况得到
			dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][0]+(sum[n]-sum[j-1]+sum[i-1])*(p[j].x-p[i].x));
			dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][1]+(sum[n]-sum[j-1]+sum[i-1])*(p[j].x-p[j-1].x));
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
const int inf=0x3f3f3f3f;
int n,v,x;
int sum[1100];
int dp[1100][1100][2];      //dp[i][j][0]表示送完i到j停在左端点i处的不满意度,dp[i][j][1]表示送完i到j停在右端点i处的不满意度
int pos;
struct node{
	int x;
	int c;
}p[1100];
bool cmp(node a,node b){
	return a.x<b.x;
}
int main(){
	while(scanf("%d%d%d",&n,&v,&x)!=EOF){
	for(int i=1;i<=n;i++){
		scanf("%d%d",&p[i].x,&p[i].c);
	}
	n++;
	p[n].x=x; p[n].c=0;
	sort(p+1,p+1+n,cmp);
	sum[0]=0;
	for(int i=1;i<=n;i++)
		sum[i]=sum[i-1]+p[i].c;
	for(int i=1;i<=n;i++)
		if(p[i].x==x){
			pos=i;
			break;
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			dp[i][j][0]=dp[i][j][1]=inf;
	dp[pos][pos][0]=dp[pos][pos][1]=0;
	for(int i=pos;i>0;i--){
		for(int j=pos;j<=n;j++){
			if(i==j) continue;
			dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][0]+(sum[n]-sum[j]+sum[i])*(p[i+1].x-p[i].x));
			dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][1]+(sum[n]-sum[j]+sum[i])*(p[j].x-p[i].x));
			dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][0]+(sum[n]-sum[j-1]+sum[i-1])*(p[j].x-p[i].x));
			dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][1]+(sum[n]-sum[j-1]+sum[i-1])*(p[j].x-p[j-1].x));
		}
	}
	cout<<min(dp[1][n][0],dp[1][n][1])*v<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Buyi.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值