2019杭电多校一 C. Milk (dp)

大意: $n*m$棋盘, 初始位置$(1,1)$, 横坐标为$\frac{m+1}{2}$时可以向下走, 否则只能左右走, 每走一步花费$1$秒. 有$k$管奶, 第$i$罐位置$(r_i,c_i)$, 要花费$t_i$的时间去喝. 对于所有的$1\le i\le k$, 求出喝完$i$管奶最短用时.

实现略复杂的$dp$题, 按照官方题解写了.

主要思路是对每一行求出向左/向右喝$x$罐奶的最少用时, 然后$dp$合并答案.

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define x first
#define y second
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const ll INF = 1e15;
const int N = 1e4+10;
int n, m, k, b[N];
struct {int x,y,t;} a[N];
ll ans[N];
vector<pii> v[N];
vector<ll> solve(vector<pii> a, int s, int x) {
	a.insert(a.begin(),pii(s,0));
	vector<ll> ret(a.size(),INF), t(ret);
	ret[0] = x==-1?0:abs(x-s);
	t[0] = 0;
	for (int i=1; i<a.size(); ++i) {
		int len = abs(a[i].x-a[i-1].x);
		REP(j,0,i-1) t[j]+=len;
		PER(j,1,i) t[j]=min(t[j],t[j-1]+a[i].y);
		REP(j,1,i) ret[j]=min(ret[j],t[j]+(x==-1?0:abs(x-a[i].x)));
	}
	return ret;
}
vector<ll> Merge(const vector<ll> &L, const vector<ll> &R) {
	vector<ll> ret(L.size()+R.size()-1,INF);
	for (int i=0;i<L.size();++i) {
		for (int j=0;j<R.size();++j) {
			ret[i+j] = min(ret[i+j], L[i]+R[j]);
		}
	}
	return ret;
}

void work() {
	scanf("%d%d%d", &n, &m, &k);
	*b = 0;
	REP(i,1,k) {
		scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].t);
		b[++*b] = a[i].x;
	}
	b[++*b] = 1;
	sort(b+1,b+1+*b),*b=unique(b+1,b+1+*b)-b-1;
	REP(i,1,*b) v[i].clear();
	REP(i,1,k) {
		a[i].x=lower_bound(b+1,b+1+*b,a[i].x)-b;
		v[a[i].x].pb(pii(a[i].y,a[i].t));
		ans[i] = INF;
	}
	REP(i,1,*b) sort(begin(v[i]),end(v[i]));
	auto g = solve(v[1],1,-1);
	for (int i=0;i<g.size();++i) {
		ans[i] = min(ans[i], g[i]);
	}
	int cur = 0;
	vector<ll> f[2];
	f[0] = solve(v[1],1,(m+1)/2);
	REP(i,2,*b) {
		cur ^= 1;
		auto p = lower_bound(begin(v[i]),end(v[i]),pii((m+1)/2,0));
		vector<pii> L(begin(v[i]),p), R(p,end(v[i]));
		reverse(begin(L),end(L));
		auto f0 = solve(L,(m+1)/2,(m+1)/2), f1 = solve(R,(m+1)/2,(m+1)/2);
		auto g0 = solve(L,(m+1)/2,-1), g1 = solve(R,(m+1)/2,-1);
		g0 = Merge(f1,g0), g1 = Merge(f0,g1);
		auto g = g0;
		for (int j=0;j<g.size();++j) {
			g[j] = min(g[j], g1[j]);
		}
		g = Merge(f[!cur],g);
		f[cur] = Merge(f[!cur],Merge(f0,f1));
		for (int j=0;j<g.size();++j) {
			ans[j] = min(ans[j], g[j]+b[i]-b[i-1]);
			f[cur][j] += b[i]-b[i-1];
		}
	}
	REP(i,1,k) {
		if (i==k) printf("%lld\n",ans[i]);
		else printf("%lld ",ans[i]);
	}
}

int main() {
	int t;
	scanf("%d", &t);
	while (t--) work();
}

原文地址:https://www.cnblogs.com/uid001/p/11249158.html

时间: 2024-10-13 22:46:02

2019杭电多校一 C. Milk (dp)的相关文章

2019杭电多校第九场

2019杭电多校第九场 熟悉的后半场挂机节奏,又苟进首页了,很快乐 1001. Rikka with Quicksort upsolved 不是我做的,1e9调和级数分段打表 1002. Rikka with Cake solved at 01:11 有一个矩形,给你很多射线(射线只有横平竖直的四个方向),问把矩形切成了多少块 队友说答案是交点数加一,作为一个合格的工具人,当然是把队友的想法实现啦 二维坐标离散化枚举纵坐标维护横坐标,常规套路,树状数组也可以做(我是线段树写习惯了根本没想起来还有

2019 杭电多校 第五场

2019 Multi-University Training Contest 5 补题链接:2019 Multi-University Training Contest 5 罚时爆炸 自闭场 1004 equation (HDU 6627) 题意: 给定一个整数 \(C\) 和 \(N\) 组 \(a_i,b_i\),求 \(∑_{i=1}^N|a_i\cdot x + b_i| = C\) 的所有解,如果有无穷多个解就输出 -1. 思路 分类讨论 分类讨论去绝对值.根据 \(b_i / a_i

2019 杭电多校 第八场

2019 Multi-University Training Contest 8 补题链接:2019 Multi-University Training Contest 8 1003 Acesrc and Good Numbers HDU 6659 题意 定义 \(f(d, n)\) 为十进制下 \(1\) 到 \(n\) 所有数的数位中数字 \(d\) 出现的次数.给定 \(x\),找出最大的 \(n(n \le x)\) 满足 \(f(d, n) = n\). 题解 看到了一个神仙做法. 显

2019杭电多校训练(一)

比赛链接: http://acm.hdu.edu.cn/search.php?field=problem&key=2019+Multi-University+Training+Contest+1&source=1&searchmode=source hdu6582 题意: 删除某些边,让$1$到$n$的最短路径发生变化 删除某条边的费用是边的长度 分析: 先用迪杰斯特拉跑一遍整个图,满足$dis[a]+w=dis[b]$的边,肯定是最短路径上的边 选出这些边,找到一个最小割集,Di

2019杭电多校&amp;CCPC网络赛&amp;大一总结

多校结束了, 网络赛结束了.发现自己还是太菜了,多校基本就是爆零和签到徘徊,第一次打这种高强度的比赛, 全英文,知识点又很广,充分暴露了自己菜的事实,发现数学还是很重要的.还是要多刷题,少玩游戏. 网络赛也打的不好, 开场写01,先是思路错,再是没考虑特判,直接罚时爆炸,再是写06,题意又看错,看了很久.其中队友过07, 我看08,队友03,08先乱写了个优先队列直接t,然后边吃边想,想到正解,忘记加换行... 最后看02, 也没写出来,队友03也是没调出来, 口上说着主攻数据结构,连想的算法都

2019 杭电多校 第七场

2019 Multi-University Training Contest 7 补题链接:2019 Multi-University Training Contest 7 1001 A + B = C 题意: 给出 \(a, b, c\),求 \(x, y, z\) 满足 \(a\cdot 10^x + b\cdot 10^y = c\cdot 10^z\).\(a, b, c \le 10^{100000}\). 题解: 补零到 \(a, b, c\) 长度相等之后,可能的情况只有四种: \

2019 杭电多校 第六场

2019 Multi-University Training Contest 6 补题链接:2019 Multi-University Training Contest 6 1002 Nonsense Time (HDU 6635) 题意 给定包含 \(n\) 个不同数字的排列 \(p\).一开始所有数字都冻住.再给出一个长度为 \(n\) 的数组 \(k\),\(k[i]\) 表示 \(p[k[i]]\) 在第 \(i\) 时刻解冻.输出 \(n\) 个数,表示第 \(i\) 个时刻数组 \(

2019 杭电多校 第一场

2019 Multi-University Training Contest 1 补题链接:2019 Multi-University Training Contest 1 1002 Operation (HDU-6579) 题意 给定包含 \(n\) 个数的序列,\(m\) 个询问.询问有两种操作,操作 \(0\) 表示在数组最后添加一个新元素,操作 \(1\) 表示查询区间 [l,r] 的子集的异或最大值. 询问强制在线. 题解 线性基 贪心 1004 Vacation (HDU-6581)

2019 杭电多校 第四场

2019 Multi-University Training Contest 4 补题链接:2019 Multi-University Training Contest 4 1001 AND Minimum Spanning Tree (HDU 6614) 题意 给定一个有 \(N\) 个结点的完全图,编号从 \(1\) 到 \(N\).结点 \(x\) 与结点 \(y\) \((1\leq x, y\leq N, x \neq y)\) 的边的权值为 \(x\) 与 \(y\) 按位与的值,求