ZOJ3469 Food Delivery (经典区间dp)

本题和某一年的oi题非常相似,都是经典套路

我们知道我们在送完食物后既可以向前送也可以回头送,这就体现了区间dp的思想

为什么我们这次的区间dp不用枚举第三维k来枚举从哪里送过来呢?

因为送货员不是傻子,他如果送到你这了,那么在你们两之间的可以都顺路送了,所以我们只需要枚举两个位置就行

这题的输入不一定递增,所以建议输入完后排序

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
ll    f[1100][1100][2];
ll s[N];
struct node{
    int x;
    int v;
    bool operator <(const node & t){
        return x<t.x;
    }
}num[N];
int main(){
    int i;
    int n;
    int v;
    int x;
    while(cin>>n>>v>>x){
        int cnt=0;
        for(i=1;i<=n;i++){
            cin>>num[i].x>>num[i].v;
        }
        n++;
        num[n].x=x;
        num[n].v=0;
        sort(num+1,num+1+n);
        int i;
        int pos;
        for(i=1;i<=n;i++)
        s[i]=s[i-1]+num[i].v;
        for(i=1;i<=n;i++){
            if(num[i].x==x){
                pos=i;
                break;
            }
        }
        memset(f,0x3f,sizeof f);
        int len,j,k;
        int l,r;
        f[pos][pos][1]=f[pos][pos][0]=0;
        for(len=2;len<=n;len++){
            for(l=1;l+len-1<=n;l++){
            r=l+len-1;
            f[l][r][1]=min(f[l+1][r][0]+(s[l]+s[n]-s[r])*(num[r].x-num[l].x),f[l+1][r][1]+(s[l]+s[n]-s[r])*(num[l+1].x-num[l].x));
            f[l][r][0]=min(f[l][r-1][0]+(s[l-1]+s[n]-s[r-1])*(num[r].x-num[r-1].x),f[l][r-1][1]+(num[r].x-num[l].x)*(s[l-1]+s[n]-s[r-1]));
            }
        }
        cout<<min(f[1][n][1],f[1][n][0])*v<<endl;
    }
}

原文地址:https://www.cnblogs.com/ctyakwf/p/12329984.html

时间: 2024-10-11 15:35:39

ZOJ3469 Food Delivery (经典区间dp)的相关文章

ZOJ 3469 Food Delivery(区间DP)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4255 题意:n个人订餐.n个人位于一条线上,饭店也在这条线上.每个人有一个脾气值p.若第i分钟得到他预定的饭不满意度为p*i.送饭人的速度已知.求一种送饭顺序使得总不满意度最小. 思路:设f[i][j][0],f[i] [j][1]分别表示将[i,j]区间的送完,最后停在左边或右边的最小不满意度.那么我们在DPf[i][j][0]时可以从f[i+1][j]进行转 移

uva348 最优矩阵链乘 经典区间dp

// uva348 最优矩阵链乘 // 典型的区间dp // dp[i][j] 表示矩阵i到j链乘所得到的最小花费 // dp[i][j] = min(dp[i][k]+dp[k+1][j]+a[i].pl*a[k].pr*a[j].pr); // 在区间i到j上找一个k使得dp[i][k]+dp[k+1][j]这两部分的和在加上最后的 // a[i].pl*a[k].pr*p[i].pr的最小值; // 能有这样的状态关键是; P =A[1] * A[2] * .... * A[K] // 和

ZOJ 3469 Food Delivery (区间DP,经典)

题意: 在x轴上有一家外卖餐馆,有n个顾客站在x轴上不同坐标上且叫了外卖,每个人的脾气不同,每1分钟没有收到外卖就会增加Fi点愤怒值,而外卖小哥的车是有速度的v-1/分钟,问怎样的送餐次序会让所有顾客的愤怒值之和最小?输出愤怒值之和! 思路: 此题是很经典了,比较现实的模型. 随便画画就知道小哥可以一下子往左一下子往右走,往返多次也是有可能的,取决于顾客的愤怒系数Fi.那么在考虑一个区间[L,R]时,其任一子区间都必须是已经被考虑过了.现在考虑区间[L,R]可以转移到哪里,明显可以分别转移到[L

poj 1390 Blocks (经典区间dp 方块消除)

Blocks Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4250   Accepted: 1704 Description Some of you may have played a game called 'Blocks'. There are n blocks in a row, each box has a color. Here is an example: Gold, Silver, Silver, Sil

石子合并问题,经典区间DP

一.直线型 问题描述: 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价最小值(或最大值). 思路: 设 DP[ i ][ j ] 表示第 i 堆合并到第 j 堆的代价的最小值(或最大值),然后,我们假设,sum[ i ] 为前 i 堆石子的总和,即前缀和.      然后就可以枚举区间长度,枚举中间点, 进行DP了, 复杂度o(n^3) dp[ i ][

POJ 1160 经典区间dp

链接http://poj.org/problem?id=1160 很好的一个题,涉及到了以前老师说过的一个题目,可惜没往那上面想. 题意,给出N个城镇的地址,他们在一条直线上,现在要选择P个城镇建立邮局,使得每个城镇到离他最近的邮局距离的总和尽量小. 首先提一个这个问题的简化版本,如果P=1得话,这个距离是多少呢? 这个问题的解就是将这个唯一的邮局建在(l+r)/2的位置,答案就是最优解, 这个类似于中位数的概念,我们有一个数学归纳法简单的证明 数轴上有n个点,求到这n个点距离最小的一个点   

POJ 2955-Brackets(区间DP)

Brackets Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3340   Accepted: 1716 Description We give the following inductive definition of a "regular brackets" sequence: the empty sequence is a regular brackets sequence, if s is a reg

uva1626 poj 1141 Brackets Sequence 区间dp 打印路径

// poj 1141 Brackets Sequence // 也是在紫书上看的一题,uva就是多了一个t组数据. // 经典区间dp // dp(i,j)表示区间[i,j]内所需要增加的括号数目 // 则分为两种情况 // 一种是s[i]和s[j]是匹配的则 // dp[i][j] = min(dp[i][j],dp[i+1][j-1]) // 另外一种情况是不匹配 // dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]){i<k<j}; // 但是无

[NYIST15]括号匹配(二)(区间dp)

题目链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=15 经典区间dp,首先枚举区间的大小和该区间的左边界,这时右边界也可计算出来.首先初始化一个匹配,那就是看看这两个括号是否匹配,即: (s[i] == '(' && s[j] == ')') || (s[i] == '[' && s[j] == ']') ? dp(i,j) = dp(i+1,j-1)+2) : dp(i,j) = 0 接下来枚举i和j中间的所