hdu多校第一场1003 (hdu6580)Milk 背包
题意:
有一个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 背包的更多相关文章
- hdu 6035:Colorful Tree (2017 多校第一场 1003) 【树形dp】
题目链接 单独考虑每一种颜色,答案就是对于每种颜色至少经过一次这种的路径条数之和.反过来思考只需要求有多少条路径没有经过这种颜色即可. 具体实现过程比较复杂,很神奇的一个树形dp,下面给出一个含较详细 ...
- hdu 多校第一场
1001 思路:打表可以发现只有3|n 和 4|n 的情况有解,判一下就好啦. #include<bits/stdc++.h> #define LL long long #define f ...
- hdu多校第一场 1006 (hdu6583)Typewriter dp/后缀自动机
题意: 有个打字机,在当前字符串后新加一个字花费p,把当前字符串的一个连续子串拷贝到当前字符串的末尾花费q,给定一个字符串,求用打字机打出这个字符串的最小花费. 题解: 容易想到用dp 记dp[i]为 ...
- hdu多校第一场1005(hdu6582)Path 最短路/网络流
题意: 在无向图上删边,让此图上从起点到终点的最短路长度变大,删边的代价是边长,求最小代价. 题解: 先跑一遍迪杰斯特拉,求出所有点的d[]值,然后在原图上保留所有的边(i,j)仅当i,j满足d[j] ...
- hdu多校第一场1004(hdu6581)Vacation 签到
题意:有n+1辆车,每辆车都有一定的长度,速度和距离终点的距离,第1-n辆车在前面依次排列,第0辆车在最后面.不允许超车,一旦后车追上前车,后车就减速,求第0辆车最快什么时候能到达终点? 思路:对于每 ...
- 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. 题解: 赛 ...
- HDU6581 Vacation (HDU2019多校第一场1004)
HDU6581 Vacation (HDU2019多校第一场1004) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6581 题意: 给你n+1辆汽车, ...
- 2019牛客多校第一场 I Points Division(动态规划+线段树)
2019牛客多校第一场 I Points Division(动态规划+线段树) 传送门:https://ac.nowcoder.com/acm/contest/881/I 题意: 给你n个点,每个点有 ...
- 牛客多校第一场 B Inergratiion
牛客多校第一场 B Inergratiion 传送门:https://ac.nowcoder.com/acm/contest/881/B 题意: 给你一个 [求值为多少 题解: 根据线代的知识 我们可 ...
随机推荐
- java ThreadPoolExecutor 异常捕获
一,创建一个线程池 其中: public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) 饱和策略执行时的具体逻辑. p ...
- scip 练习2.20
(define (same-parity x . z) (define (q? y) (= (remainder y ) )) (define (o? y) (= (remainder y ) )) ...
- ps使logo背景色透明
方法一:魔法工具(对复杂的logo误差较大) 魔法工具--左键点击选区--delete--保存 方法二:拾色器 1.有的站上的素材图片不能直接用,需要先变成rgb图像,可这样操作:图像\模式,选择rg ...
- delphi DBGrid简单自绘(字体颜色、背景等)
delphi DBGrid简单自绘(字体颜色.背景等) 从网上找的代码 应该是C#写的,其实delphi 的操作类似: 1 2 3 4 5 6 7 8 9 10 11 12 13 void __fa ...
- 【缓存】缓存穿透、缓存雪崩、key重建方案
一.缓存穿透预防及优化 缓存穿透是指查询一个根本不存在的数据,缓存层和存储层都不会命中,但是出于容错的考虑,如果从存储层查不到数据则不写入缓存层,如图 11-3 所示整个过程分为如下 3 步: 缓存层 ...
- bzoj1293题解
[题意分析] 给你一条有n个点的数轴,每个点属于一个种类,总共有k个种类.求一段最短的线段,使对于每个种类,这段线段上有至少一个点属于它. [算法分析] 1.对于50%的数据,N≤10000 对于每一 ...
- NX二次开发-UFUN输入对象tag获得part名字UF_OBJ_ask_owning_part
NX11+VS2013 #include <uf.h> #include <uf_modl.h> #include <uf_part.h> #include < ...
- 如何通过编程发现Java死锁
本文由 ImportNew - rookie_sam 翻译自 Dzone.欢迎加入翻译小组.转载请见文末要求. 死锁是指,两个或多个动作一直在等待其他动作完成而使得所有动作都始终处在阻塞的状态.想要在 ...
- CSS3:CSS3 渐变(Gradients)
ylbtech-CSS3:CSS3 渐变(Gradients) 1.返回顶部 1. CSS3 渐变(Gradients) CSS3 渐变(gradients)可以让你在两个或多个指定的颜色之间显示平稳 ...
- jquery click事件失效
除了最基本的语法错误,还可能是因为,元素根本点击不到. z-index:99;