ZOJ 3469 Food Delivery -- 区间dp

来源:互联网 发布:三轴点胶机编程教学 编辑:程序博客网 时间:2024/05/16 04:39

题目链接点击打开链接


题意:一条直线上有n个人点外卖。每个人都有一个坐标xi。每个人都有一个不开心值,每过一秒不开心值增加一倍,初始值都为0。外卖小哥初始在点x上,以速度v-1给这直线上的n个人送外卖。求不开心值总和最少多少。


思路:区间dp。这是一类当前决策对未来有影响的dp,方法是将当前决策对未来的影响直接加到当前。

dp[i][j][0]表示区间i到j且停在i点的最小值,dp[i][j][1]表示间i到j且停在j点的最小值。令sum[i]表示从点1到点i的不开心值总和。

dp[i][j][0] = min(dp[i][j][0],dp[i+1][j][0]+(a[i+1].x-a[i].x)*(sum[i]+sum[n]-sum[j]);

dp[i][j][0] = min(dp[i][j][0],dp[i+1][j][1]+(a[j].x-a[i].x)*(sum[i]+sum[n]-sum[j]);

dp[i][j][1] = min(dp[i][j][1],dp[i][j-1][0]+(a[j].x-a[i].x)*(sum[i-1]+sum[n]-sum[j-1]);

dp[i][j][1] = min(dp[i][j][1],dp[i][j-1][1]+(a[j].x-a[j-1].x)*(sum[i-1]+sum[n]-sum[j-1]);

最终结果为 min(dp[i][j][0],dp[i][j][1])*(v-1)。


AC代码

#include<iostream>#include<cstdio>#include<cstring>#include<stack>#include <algorithm>#include <cmath>using namespace std;const int N = 1015;const int INF =  0x3f3f3f3f;typedef long long LL;struct node{    int x,b;} a[N];bool cmp(node aa,node b){    return aa.x<b.x;}int  dp[N][N][2],sum[N];///dp[i][j][0]  means end at the left///dp[i][j][1]  means end at the rightint main(){    int n,v,x,sta;    while(scanf("%d%d%d",&n,&v,&x)==3)    {        for(int i=1; i<=n; i++) scanf("%d%d",&a[i].x,&a[i].b);        n++;        a[n].x = x,a[n].b = 0;        sort(a+1,a+n+1,cmp);        sum[0] = 0;        for(int i = 1; i<=n; i++)        {            sum[i] = sum[i-1] + a[i].b;            if(a[i].x == x)            {                sta = i;            }        }        for(int i=0; i<=n; i++)            for(int j=0; j<=n; j++) dp[i][j][0] = dp[i][j][1] = INF;        dp[sta][sta][0] = dp[sta][sta][1] = 0;        for(int i=sta; i>=1; i--)        {            for(int j=i+1; j<=n; j++)            {               // if(i==j) continue;                ///end at left                dp[i][j][0] = min(dp[i][j][0],dp[i+1][j][0]+(sum[n]-sum[j]+sum[i])*(a[i+1].x-a[i].x));                dp[i][j][0] = min(dp[i][j][0],dp[i+1][j][1]+(sum[n]-sum[j]+sum[i])*(a[j].x-a[i].x));                ///end at right                dp[i][j][1] = min(dp[i][j][1],dp[i][j-1][0]+(sum[n]-sum[j-1]+sum[i-1])*(a[j].x-a[i].x));                dp[i][j][1] = min(dp[i][j][1],dp[i][j-1][1]+(sum[n]-sum[j-1]+sum[i-1])*(a[j].x-a[j-1].x));            }        }        printf("%d\n",v*min(dp[1][n][0],dp[1][n][1]));    }    return 0;}





                 

0 0
原创粉丝点击