1、http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4255
好题,思维强度挺大,得好好理解各个状态的转换
2、题目大意:
有一家快餐店送外卖,现在同时有n个家庭打进电话订购,送货员得以V-1的速度一家一家的运送,但是每一个家庭都有一个不开心的值,每分钟都会增加一倍,值达到一定程度,该家庭将不会再订购外卖了,现在为了以后有更多的家庭订购,要将外卖送到的情况下使得所有用户的不开心值总和达到最小
很明显,每多走一分钟,没送到的家庭的不开心值都会加倍,
假设是这样的顺序123X456,从X出发先往左右中间靠近的送,再往两边送省时间
dp[i][j][0]表示从i到j用户送到最小不开心值,此时送货员停留在左边即i位置
dp[i][j][1]表示从i到j用户送到最小不开心值,此时送货员停留在右边即j位置
状态有四种,
dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][0]+(a[i+1].x-a[i].x)*(delay+a[i].v));
dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][1]+(a[j].x-a[i].x)*(delay+a[i].v));
dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][0]+(a[j].x-a[i].x)*(delay+a[j].v));
dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][1]+(a[j].x-a[j-1].x)*(delay+a[j].v));
3、AC代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 1005
#define INF 0x7ffffff
int dp[N][N][2];
int n,V,X;
int sum[N];
struct node
{
int x;
int v;
} a[N];
int cmp(node b,node c)
{
return b.x<c.x;
}
int Delay(int l,int r)
{
if(l>r)
return 0;
return sum[r]-sum[l-1];
}
void DP()
{
int res;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
dp[i][j][0]=dp[i][j][1]=INF;
}
for(int i=1; i<=n; i++)
{
if(a[i].x==X)
{
res=i;
break;
}
}
dp[res][res][0]=dp[res][res][1]=0;
for(int i=res; i>=1; i--)//i循环restaurant左边的
{
for(int j=res; j<=n; j++)//j循环restaurant右边的
{
int delay=Delay(1,i-1)+Delay(j+1,n);
if(i==j)
continue;
dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][0]+(a[i+1].x-a[i].x)*(delay+a[i].v));
dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][1]+(a[j].x-a[i].x)*(delay+a[i].v));
dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][0]+(a[j].x-a[i].x)*(delay+a[j].v));
dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][1]+(a[j].x-a[j-1].x)*(delay+a[j].v));
}
}
}
int main()
{
while(scanf("%d%d%d",&n,&V,&X)!=EOF)
{
for(int i=1; i<=n; i++)
{
scanf("%d%d",&a[i].x,&a[i].v);
}
a[n+1].x=X;
a[n+1].v=0;
n++;
sort(a+1,a+n+1,cmp);
memset(sum,0,sizeof(sum));
for(int i=1; i<=n; i++)
sum[i]=sum[i-1]+a[i].v;
DP();
printf("%d\n",min(dp[1][n][0],dp[1][n][1])*V);
}
return 0;
}