题意:

有一个n*m的矩阵,左右可以随便走,但只能在每一行的中点往下走,每走一格花费时间1.

现在这个矩阵里放了k瓶牛奶,第i个牛奶喝下去需要ti时间

起点是(1,1)

对于每个i∈[1,k],问喝掉k瓶牛奶花费的最小时间

题解:

首先离散化行。

记第 i 行的牛奶数为 ci,则对于第 i 行,求出在行内向左/右走喝 1,2,...,ci 包牛奶并 且回到/不回到行中点的最短时间,然后合并背包求出在第 i 行内喝 1,2,...,ci 包牛奶并且 回到/不回到行中点的最短时间,然后和在前 i−1 行喝牛奶并回到中点的背包合并,求出 在前 i 行内喝 1,2,...,k 包牛奶并且回到/不回到行中点的最短时间,并用不回到中点的背包 更新答案。每一行处理的复杂度为 O(kci),因此总复杂度为 O(k2)。

注意对第一行因为是从最左边而不是中间开始,所以要特殊处理。

#include<bits/stdc++.h>
#define MAXN 10004
#define LL long long
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
struct Milk{
int x,y,t;
friend bool operator >(const Milk &a,const Milk &b){
return a.y>b.y;
}
friend bool operator <(const Milk &a,const Milk &b){
return a.y<b.y;
} Milk(){}
Milk(int a,int b,int c){
x=a;y=b;t=c;
}
}milk[MAXN];
vector<LL> solve(const vector<Milk> &a,int dest){
//调用引用,减小常数
//背包算出停在dest点花费最小时间
//若dest为0则不限制停在哪一点
vector<LL> c(a.size(),INF);
vector<LL> t(a.size(),INF);
c[]=(dest==-)?:abs(dest-a[].y);
t[]=;
for(int i=;i<a.size();++i){
int len=abs(a[i].y-a[i-].y);
for(int j=;j<i;++j)t[j]+=len;
for(int j=i;j>=;--j)t[j]=min(t[j],t[j-]+a[i].t);
for(int j=;j<=i;++j){
LL tmp=t[j]+(dest==-?:abs(dest-a[i].y));
c[j]=min(c[j],tmp);
}
}
return c;
}
vector<LL> Merge(const vector<LL> &a,const vector<LL> &b){
vector<LL> c(a.size()+b.size()-,INF);
for(int i=;i<a.size();++i){
for(int j=;j<b.size();++j){
c[i+j]=min(c[i+j],a[i]+b[j]);
}
}
//两个参数分别是朝向两个方向喝多少瓶牛奶花费最少时间,把这俩合并
return c;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
int n,m,k;
scanf("%d %d %d",&n,&m,&k);
vector<int> disc;
disc.push_back();
for(int i=;i<=k;i++){
scanf("%d %d %d",&milk[i].x,&milk[i].y,&milk[i].t);
disc.push_back(milk[i].x);
}
sort(disc.begin(),disc.end());
disc.erase(unique(disc.begin(),disc.end()),disc.end());
//去重
vector<Milk> a[MAXN];
LL Ans[MAXN];
for(int i=;i<disc.size();++i)a[i].clear(); for(int i=;i<=k;++i){
int tmp=lower_bound(disc.begin(),disc.end(),milk[i].x)-disc.begin();
a[tmp].push_back(milk[i]);
Ans[i]=INF;
}
//将行离散化
for(int i=;i<disc.size();++i){
sort(a[i].begin(),a[i].end());
}
vector<LL> f[];//存储结果
vector<Milk> t=a[];//存储当前行 t.insert(t.begin(),Milk(,,)); f[]=solve(t,(m+)/);
vector<LL> g=solve(t,-);
for(int i=;i<t.size();++i)Ans[i]=min(Ans[i],g[i]); for(int i=;i<disc.size();++i) {
vector<Milk>::iterator sp=lower_bound(a[i].begin(),a[i].end(),Milk(i,(m+)/,));
vector<Milk> t0(a[i].begin(),sp);
vector<Milk> t1(sp,a[i].end()); t0.push_back(Milk(i,(m+)/,));
reverse(t0.begin(),t0.end()); t1.insert(t1.begin(),Milk(i,(m+)/,)); vector<LL> f0,f1,g0,g1;
f0=solve(t0,(m+)/);
f1=solve(t1,(m+)/);
g0=solve(t0,-);
g1=solve(t1,-);
//向两个方向分别背包 g0=Merge(f1,g0);
g1=Merge(f0,g1); vector<LL> g(g0.size()); for(int j=;j<g.size();++j){
g[j]=min(g0[j],g1[j]);
} g=Merge(f[(i-)&],g);
//把每层的背包合并 f[i&]=Merge(f[(i-)&],Merge(f0,f1)); for(int j=;j<g.size();++j) {
Ans[j]=min(Ans[j],g[j]+=disc[i]-disc[i-]);
f[i&][j]+=disc[i]-disc[i-];
}
} for(int i=;i<k;i++){
printf("%lld ",Ans[i]);
}
printf("%lld\n",Ans[k]);
}
}

hdu多校第一场1003 (hdu6580)Milk 背包的更多相关文章

  1. hdu 6035:Colorful Tree (2017 多校第一场 1003) 【树形dp】

    题目链接 单独考虑每一种颜色,答案就是对于每种颜色至少经过一次这种的路径条数之和.反过来思考只需要求有多少条路径没有经过这种颜色即可. 具体实现过程比较复杂,很神奇的一个树形dp,下面给出一个含较详细 ...

  2. hdu 多校第一场

    1001 思路:打表可以发现只有3|n 和 4|n 的情况有解,判一下就好啦. #include<bits/stdc++.h> #define LL long long #define f ...

  3. hdu多校第一场 1006 (hdu6583)Typewriter dp/后缀自动机

    题意: 有个打字机,在当前字符串后新加一个字花费p,把当前字符串的一个连续子串拷贝到当前字符串的末尾花费q,给定一个字符串,求用打字机打出这个字符串的最小花费. 题解: 容易想到用dp 记dp[i]为 ...

  4. hdu多校第一场1005(hdu6582)Path 最短路/网络流

    题意: 在无向图上删边,让此图上从起点到终点的最短路长度变大,删边的代价是边长,求最小代价. 题解: 先跑一遍迪杰斯特拉,求出所有点的d[]值,然后在原图上保留所有的边(i,j)仅当i,j满足d[j] ...

  5. hdu多校第一场1004(hdu6581)Vacation 签到

    题意:有n+1辆车,每辆车都有一定的长度,速度和距离终点的距离,第1-n辆车在前面依次排列,第0辆车在最后面.不允许超车,一旦后车追上前车,后车就减速,求第0辆车最快什么时候能到达终点? 思路:对于每 ...

  6. hdu多校第一场 1013(hdu6590)Code 凸包交

    题意: 给定一组(x1,x2,y),其中y为1或0,问是否有一组(w1,w2,b),使得上述的每一个(x1,x2,y)都满足x1*w1+x2*w2+b在y=1时大于0,在y=-1时小于0. 题解: 赛 ...

  7. HDU6581 Vacation (HDU2019多校第一场1004)

    HDU6581 Vacation (HDU2019多校第一场1004) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6581 题意: 给你n+1辆汽车, ...

  8. 2019牛客多校第一场 I Points Division(动态规划+线段树)

    2019牛客多校第一场 I Points Division(动态规划+线段树) 传送门:https://ac.nowcoder.com/acm/contest/881/I 题意: 给你n个点,每个点有 ...

  9. 牛客多校第一场 B Inergratiion

    牛客多校第一场 B Inergratiion 传送门:https://ac.nowcoder.com/acm/contest/881/B 题意: 给你一个 [求值为多少 题解: 根据线代的知识 我们可 ...

随机推荐

  1. VACUUM - 垃圾收集以及可选地分析一个数据库

    SYNOPSIS VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ table ] VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANA ...

  2. Logstash详解之——filter模块-grok插件

    1. grok插件:能匹配一切数据,但是性能和对资源的损耗也很大. grok内置字段类型参见: https://blog.csdn.net/cui929434/article/details/9439 ...

  3. Unity3d -- Collider(碰撞器与触发器)

    (2d与3d的Collider可以相互存在,但是无法相互协作,如2d是无法检测3d的,反之,一样) 在目前掌握的情况分析,在Unity中参与碰撞的物体分2大块:1.发起碰撞的物体.2.接收碰撞的物体. ...

  4. shell脚本实现批量端口扫描

    #!/bin/bash # Telnet Batach readonly TMOUT= ip_prefix="192.168" ip_network_range="80- ...

  5. Laravel 项目运行 phpunit 测试结果只显示点号

    在laravel 项目的根目录下,运行 phpunit 只显示 点号的情况 我尝试将 tests/Unit 和 tests/Feature 目录将 ExampleTest.php 文件删除,然后再运行 ...

  6. springcloud -zuul(1-zuul的简单使用)

    1.maven引入包 <dependency> <groupId>org.springframework.cloud</groupId> <artifactI ...

  7. Redis Desktop Manager可视化工具连接不上redis

    1.在centos中启动redis之后,redis进程也是可查的,但是一连接可视化工具就报错: can't connect to redis-server 2.原因分析: ①首先redis是肯定已经开 ...

  8. leetcood学习笔记-107-二叉树的层次遍历二

    题目描述: 方法一: class Solution(object): def levelOrderBottom(self, root): """ :type root: ...

  9. NX11.0和VS2013 创建NXOpen 开发模版失败解决方案【转载】

    转载自PLM之家论坛 NX11.0和VS2013 创建NXOpen 开发模版失败解决方案 首先我觉得这个可能是西门子疏忽,基本上每个大版本没有补丁前都有类似问题,下面来说说怎么解决吧.注意这里版本,N ...

  10. Photon Server的服务器端配置

    Photon Server与Unity3D的交互分为3篇博文实现 (1)Photon Server的服务器端配置 (2)Photon Server的Unity3D客户端配置 (3)Photon Ser ...