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 题意: 给你一个 [求值为多少 题解: 根据线代的知识 我们可 ...
随机推荐
- 使用自己的Python函数处理Protobuf中的字符串编码
我目前所在的项目是一个老项目,里面的字符串编码有点乱,数据库中有些是GB2312,有些是UTF8:代码中有些是GBK,有些是UTF8,代码中转来转去,经常是不太清楚当前这个字符串是什么编码,由于是老项 ...
- Delphi GDI(一)
Delphi 7下IGDIPlus库的使用 IGDI+是一个免费开源封装微软GDI+功能的Delphi库,该库使得可以用Delphi语言代码快速简短的实现复杂GDI+应用程序. 官方网站:http:/ ...
- [转]gulp打包工具总结
与grunt类似,gulp也是构建工具,但相比于grunt的频繁IO操作,gulp的流操作能更快更便捷地完成构建工作.gulp借鉴了Unix操作系统的管道(pipe)思想,前一级的输出,直接变成后一级 ...
- 在WinDBG中查看内存的命令
当我们在调试器中分析问题时, 经常需要查看不同内存块的内容以分析产生的原因, 并且在随后验证所做出的假设是否正确. 由于各个对象的状态都是保存在内存中的, 因此内存的内容也就相当于对象的状态. d命令 ...
- ionic:temple
ylbtech-ionic:temple 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 6.返回顶部 作者:ylbtech出处:http://ylb ...
- java之jvm学习笔记六(实践写自己的安全管理器)
安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用AccessController的checkPerssiom方法,访问控 ...
- 2019 牛客多校第一场 F Random Point in Triangle
题目链接:https://ac.nowcoder.com/acm/contest/881/F 题目大意 给定二维平面上 3 个整数表示的点 A,B,C,在三角形 ABC 内随机选一点 P,求期望$E ...
- C++11多线程程序运行错误
编译没有问题,错误如图: 错误原因: http://stackoverflow.com/questio ... ation-not-permitted gcc4.6以后对于ld自动加上了as-need ...
- java 传入多个参数时报"Parameter 'XXX' not found. Available parameters are [arg1, arg0, param1,..." 解决方案
@Select("SELECT id FROM ae_post ORDER BY id DESC LIMIT #{page},#{size}") List<Post> ...
- Vue项目的配置项
目录 Vue项目的配置项 配置项 加载全局css文件 加载全局js文件 store仓库的配置和简单用法 BootStrap环境和jQuery的配置 前端后端交互(CORS问题) axios配置项(前端 ...