题目链接: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;
}