原题链接:
题目大意:
送餐员送餐问题。有n个人叫餐,每个人都在x轴上,并且每个人都有个XX度(和等餐时间有关,据说顾客认为xx值到一定程度他的小宇宙就要爆发).现在送餐员从x轴上的某点出发,路上奔跑速度是v^-1,要一次性把所有餐送完。叫餐的人得到餐的时间和顺序不同,xx度总和也就不同。合格的送餐员要让客户体验最好,请问最少xx度和为多少
这题的做法和poj3042相似,在做当前的选择时要把当前的选择对以后的影响计算进去,
首先用 dp[i][j][0] 表示送完i--j之间的顾客后在i位置时的最小值 ,dp[i][j][1] 表示送完i--j之间的顾客后在j位置时的最小值
动态转移方程:
dp[i][j][1]=min(dp[i][j-1][1]+(cost[n]-cost[j-1]+cost[i-1])*(p[j].x-p[j-1].x),dp[i][j-1][0]+(cost[n]-cost[j-1]+cost[i-1])*(p[j].x-p[i].x));
dp[i][j][0]=min(dp[i+1][j][0]+(cost[n]-cost[j]+cost[i])*(p[i+1].x-p[i].x),dp[i+1][j][1]+(cost[n]-cost[j]+cost[i])*(p[j].x-p[i].x));
ps:由于没看清v的含义,无限受伤啊,。。。 (v不是速度额,亲)
喳喳代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1100
using namespace std;
struct node
{
int x,b;
} p[N];
int n,v,x0,s;
int dp[N][N][2];
int cost[N];
bool cmp(node a,node b)
{
return a.x<b.x;
}
int solve()
{
memset(dp,0x3f,sizeof(dp));//这个最大值不能太大,否则下面转移方程会尴尬。。。
dp[s][s][0]=dp[s][s][1]=0;
for(int i=s; i>0; i--)
for(int j=s; j<=n; j++)
{
if(i==s&&j==s)continue; //可以暂时不用速度,最后再处理
dp[i][j][1]=min(dp[i][j-1][1]+(cost[n]-cost[j-1]+cost[i-1])*(p[j].x-p[j-1].x),dp[i][j-1][0]+(cost[n]-cost[j-1]+cost[i-1])*(p[j].x-p[i].x));
dp[i][j][0]=min(dp[i+1][j][0]+(cost[n]-cost[j]+cost[i])*(p[i+1].x-p[i].x),dp[i+1][j][1]+(cost[n]-cost[j]+cost[i])*(p[j].x-p[i].x));
}
return min(dp[1][n][0],dp[1][n][1]);
}
int main()
{
// freopen("in.txt","r",stdin);
while(scanf("%d%d%d",&n,&v,&x0)!=EOF)
{
bool flag=false;
for(int i=1; i<=n; i++)
{
scanf("%d%d",&p[i].x,&p[i].b);
if(p[i].x==x0)
flag=true;
}
if(!flag)
{
p[n+1].x=x0;
p[n+1].b=0;
n++;
}
sort(p+1,p+1+n,cmp);
for(int i=1; i<=n; i++)
if(p[i].x==x0)
{
s=i;
break;
}
cost[0]=0;
for(int i=1; i<=n; i++)
cost[i]=cost[i-1]+p[i].b;
printf("%d\n",v*solve());
}
return 0;
}