• zoj 3469 Food Delivery


    zoj 3469 Food Delivery

    题面

    一维数轴上有一个外卖配送员和 (1000) 个客户,每个客户 (i) 的怒气值是他收到外卖的时间乘 (b[i])(b[i]) 由题目给定),给出配送员速度,求一个方案使得所有客户的怒气值之和最小,输出最小怒气值之和。

    题解

    收到货的客户一定处在连续的一段区间内,做法是区间dp。
    我们用 (v_i) 表示第 (i) 个收到外卖的客户的 (b) 值,(x_i) 表示第 (i) 个收到外卖的客户的坐标。 (O) 表示配送员初始坐标。

    (总的怒气值=)
    (v_1*(|x_1-O|) +)
    (v_2*(|x_1-O|+|x_2-x_1|) +)
    (v_3*(|x_1-O|+|x_2-x_1|+|x_3-x_2|) +)
    (... +)
    (v_n*(|x_1-O|+|x_2-x_1|+|x_3-x_2|+...+|x_n-x_{n-1}|))

    (=)
    (|x_1-O|*(v_1+v_2+...+v_n) +)
    (|x_2-x_1|*(v_2+...+v_n) +)
    (... +)
    (|x_n-x_{n-1}|*(v_n))

    (f[i][j][0])表示(i)(j)这段区间的客户都已经收到外卖,此时外卖员在(i)处,假设这段区间有(t)个人。(f[i][j][0])为上式中前(t)行。

    (f[i][j][1])表示外卖员在(j)处,其他与(f[i][j][0])同理。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define rep(i, a, b) for(int i=(a); i<(b); i++)
    #define sz(x) (int)x.size()
    #define de(x) cout<< #x<<" = "<<x<<endl
    #define dd(x) cout<< #x<<" = "<<x<<" "
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef vector<int> vi;
    //------
    
    const int N=1010;
    const ll inf=(1ll<<31);
    int n,v,x;
    ll f[N][N][2], sum[N];
    pii a[N];
    
    ll Sum(int l,int r) {
    	ll ans=sum[n+1]-(sum[r+1]-sum[l]);
    	return ans;
    }
    
    int main() {
    	while(~scanf("%d%d%d",&n,&v,&x)) {
    		///init
    		rep(i,0,n+1) rep(j,0,n+1) rep(k,0,2) f[i][j][k]=inf;
    		///read
    		rep(i,1,n+1) {
    			int x,y;scanf("%d%d",&x,&y);
    			a[i]=mp(x,y);
    		}
    		///solve
    		a[0]=mp(x,-1);
    		sort(a,a+n+1);
    		rep(i,0,n+1) sum[i+1]=sum[i]+max(a[i].se, 0);
    		rep(i,0,n+1) if(a[i].se==-1) f[i][i][0]=f[i][i][1]=0;
    		rep(len,1,n+1) {
    			for(int i=0;i+len<=n;++i) {
    				int j=i+len;
    				ll t0=1ll*(a[i+1].fi-a[i].fi)*Sum(i+1, j);
    				ll t1=1ll*(a[j].fi-a[i].fi)*Sum(i+1, j);
    				f[i][j][0]=min(f[i+1][j][0]+t0,f[i+1][j][1]+t1);
    				ll t2=1ll*(a[j].fi-a[i].fi)*Sum(i, j-1);
    				ll t3=1ll*(a[j].fi-a[j-1].fi)*Sum(i, j-1);
    				f[i][j][1]=min(f[i][j-1][0]+t2,f[i][j-1][1]+t3);
    			}
    		}
    		printf("%lld
    ",min(f[0][n][0], f[0][n][1])*v);
    	}
    	return 0;
    }
    
  • 相关阅读:
    open stack总结
    Nginx操作命令
    Nginx 配置详解
    Linux 常用命令-- top
    CEPH 使用SSD日志盘+SATA数据盘, 随OSD数目递增对性能影响的递增测试
    MyCat水平分库
    MyCat垂直分库
    MyCat基本知识
    utf8mb4复杂昵称问题
    Power安装linux-BIG ENDIAN mysql编译安装
  • 原文地址:https://www.cnblogs.com/wuyuanyuan/p/8278886.html
Copyright © 2020-2023  润新知