首页 > 其他分享 >AtCoder Beginner Contest 258 F Main Street

AtCoder Beginner Contest 258 F Main Street

时间:2023-06-11 19:24:33浏览次数:38  
标签:AtCoder sxb eyb abs Beginner Contest syb add edge

洛谷传送门

AtCoder 传送门

发现这题有个远古的 WA 就来改了(

发现走法很多种,不想分类讨论,考虑最短路。

设起点编号为 \(1\),终点为 \(11\)。

\(x = Bn\) 和 \(y = Bn\) 把坐标系分成了若干块。考虑过起点作一条平行于 \(Ox\) 的直线,与左右两条 \(x = Bn\) 的线有两个交点,给它们编号 \(3, 5\),同样地作一条平行于 \(Oy\) 的直线,与上下两条 \(y = Bn\) 的线有两个交点,给它们编号 \(4, 2\)。然后把起点所在块的四个角分别编号 \(6, 7, 8, 9\),然后连 \(1 \to 2, 3, 4, 5\),\(2, 3, 4, 5\) 再连到 \(6, 7, 8, 9\),像这样:

对于终点也是类似地建图,编号相对于起点 \(+ 10\)。

那对于起点和终点不在一个块的情况,先走到起点所在块的四个角的一个再走到终点所在块四个角的一个是一种备选方案。因此连边 \(x \to y + 10, x, y \in \{6, 7, 8, 9\}\),边权可以算出来。

在同一个块内,或者起点终点两个块相邻,可以不走到四个角,这个要特判,连相应的边。这里因为连边较复杂不展开,可以看代码。

然后跑一遍 \(1\) 到 \(11\) 的最短路就行。

code
#include <bits/stdc++.h>
#define pb push_back
#define fst first
#define scd second

using namespace std;
typedef long long ll;
typedef pair<ll, ll> pii;

ll B, K, sx, sy, ex, ey, head[30], len;
ll dis[30];
bool vis[30];

struct edge {
	ll to, dis, next;
} edges[10000];

struct node {
	ll dis, pos;
	node() {}
	node(ll a, ll b) : dis(a), pos(b) {}
	bool operator < (const node &u) const {
		return dis > u.dis;
	}
};

void add_edge(ll u, ll v, ll d) {
	// printf("%lld %lld %lld\n", u, v, d);
	edges[++len].to = v;
	edges[len].dis = d;
	edges[len].next = head[u];
	head[u] = len;
}

void solve() {
	len = 0;
	memset(head, 0, sizeof(head));
	memset(dis, 0x3f, sizeof(dis));
	memset(vis, 0, sizeof(vis));
	scanf("%lld%lld%lld%lld%lld%lld", &B, &K, &sx, &sy, &ex, &ey);
	ll sxb = (sx - 1) / B + 1, syb = (sy - 1) / B + 1;
	ll exb = (ex - 1) / B + 1, eyb = (ey - 1) / B + 1;
	add_edge(1, 2, (sy - (syb - 1) * B) * K);
	add_edge(1, 3, (sx - (sxb - 1) * B) * K);
	add_edge(1, 4, (syb * B - sy) * K);
	add_edge(1, 5, (sxb * B - sx) * K);
	add_edge(2, 6, sx - (sxb - 1) * B);
	add_edge(2, 9, sxb * B - sx);
	add_edge(3, 6, sy - (syb - 1) * B);
	add_edge(3, 7, syb * B - sy);
	add_edge(4, 7, sx - (sxb - 1) * B);
	add_edge(4, 8, sxb * B - sx);
	add_edge(5, 8, syb * B - sy);
	add_edge(5, 9, sy - (syb - 1) * B);
	add_edge(6, 7, B);
	add_edge(6, 9, B);
	add_edge(9, 6, B);
	add_edge(9, 8, B);
	add_edge(8, 9, B);
	add_edge(8, 7, B);
	add_edge(7, 8, B);
	add_edge(7, 6, B);
	// -----------------------------------
	add_edge(12, 11, (ey - (eyb - 1) * B) * K);
	add_edge(13, 11, (ex - (exb - 1) * B) * K);
	add_edge(14, 11, (eyb * B - ey) * K);
	add_edge(15, 11, (exb * B - ex) * K);
	add_edge(16, 12, ex - (exb - 1) * B);
	add_edge(19, 12, exb * B - ex);
	add_edge(16, 13, ey - (eyb - 1) * B);
	add_edge(17, 13, eyb * B - ey);
	add_edge(17, 14, ex - (exb - 1) * B);
	add_edge(18, 14, exb * B - ex);
	add_edge(18, 15, eyb * B - ey);
	add_edge(19, 15, ey - (eyb - 1) * B);
	add_edge(16, 17, B);
	add_edge(16, 19, B);
	add_edge(19, 16, B);
	add_edge(19, 18, B);
	add_edge(18, 19, B);
	add_edge(18, 17, B);
	add_edge(17, 18, B);
	add_edge(17, 16, B);
	// -----------------------------------
	add_edge(6, 16, (abs(sxb - exb) + abs(syb - eyb)) * B);
	add_edge(6, 19, (abs(sxb - 1 - exb) + abs(syb - eyb)) * B);
	add_edge(6, 17, (abs(sxb - exb) + abs(syb - eyb - 1)) * B);
	add_edge(6, 18, (abs(sxb - 1 - exb) + abs(syb - eyb - 1)) * B);
	add_edge(9, 16, (abs(sxb + 1 - exb) + abs(syb - eyb)) * B);
	add_edge(9, 19, (abs(sxb - exb) + abs(syb - eyb)) * B);
	add_edge(9, 17, (abs(sxb + 1 - exb) + abs(syb - eyb - 1)) * B);
	add_edge(9, 18, (abs(sxb - exb) + abs(syb - eyb - 1)) * B);
	add_edge(7, 16, (abs(sxb - exb) + abs(syb + 1 - eyb)) * B);
	add_edge(7, 19, (abs(sxb - 1 - exb) + abs(syb + 1 - eyb)) * B);
	add_edge(7, 17, (abs(sxb - exb) + abs(syb - eyb)) * B);
	add_edge(7, 18, (abs(sxb - 1 - exb) + abs(syb - eyb)) * B);
	add_edge(8, 16, (abs(sxb + 1 - exb) + abs(syb + 1 - eyb)) * B);
	add_edge(8, 19, (abs(sxb - exb) + abs(syb + 1 - eyb)) * B);
	add_edge(8, 17, (abs(sxb + 1 - exb) + abs(syb - eyb)) * B);
	add_edge(8, 18, (abs(sxb - exb) + abs(syb - eyb)) * B);
	// printf("%lld %lld %lld %lld %lld\n", sx, sy, ex, ey, K);
	// -----------------------------------
	if (sxb == exb && syb == eyb - 1) {
		add_edge(4, 12, abs(sx - ex));
	} else if (sxb == exb && syb == eyb + 1) {
		add_edge(2, 14, abs(sx - ex));
	} else if (sxb == exb - 1 && syb == eyb) {
		add_edge(5, 13, abs(sy - ey));
	} else if (sxb == exb + 1 && syb == eyb) {
		add_edge(3, 15, abs(sy - ey));
	}
	
	if (sxb == exb && syb == eyb) {
		add_edge(2, 12, abs(sx - ex));
		add_edge(3, 13, abs(sy - ey));
		add_edge(4, 14, abs(sx - ex));
		add_edge(5, 15, abs(sy - ey));
	}
	
	add_edge(1, 11, (abs(sx - ex) + abs(sy - ey)) * K);
	priority_queue<node> pq;
	pq.push(node(0, 1));
	dis[1] = 0;
	while (pq.size()) {
		int u = pq.top().pos;
		pq.pop();
		if (vis[u]) {
			continue;
		}
		vis[u] = 1;
		for (int i = head[u]; i; i = edges[i].next) {
			ll v = edges[i].to, d = edges[i].dis;
			if (dis[v] > dis[u] + d) {
				dis[v] = dis[u] + d;
				if (!vis[v]) {
					pq.push(node(dis[v], v));
				}
			}
		}
	}
	printf("%lld\n", dis[11]);
}

int main() {
	int T = 1;
	scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:AtCoder,sxb,eyb,abs,Beginner,Contest,syb,add,edge
From: https://www.cnblogs.com/zltzlt-blog/p/17473402.html

相关文章

  • AtCoder Beginner Contest 305
    A-WaterStation(abc305a)题目大意给定一个数字\(x\),输出一个数字,它是最接近\(x\)的\(5\)的倍数。解题思路令\(y=x\%5\),如果\(y\leq2\),那答案就是\(x-y\),否则就是\(x+5-y\)。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=long......
  • ATCoder [ABC167D] Teleporter
    #题目解析这段代码的目标是处理一个含有$n$个元素的整数序列,根据一定的规则,重复操作$k$次后,确定操作结束时位于序列哪个位置。##解题思路1.**读取输入**:首先,我们读取输入的整数$n$和$k$,以及整数序列`a`。我们需要对序列的每个元素减一,以适应从0开始的索引。cin......
  • AtCoder Beginner Contest 290 Ex Bow Meow Optimization
    洛谷传送门AtCoder传送门考虑观察答案形态。当\(n,m\)均为偶数时,前一半位置有\(\frac{n}{2}\)个是狗,\(\frac{m}{2}\)个是猫。并且前半段从前往后和后半段从后往前都是按权值从小到大放。调整法证明即可。当\(n\)或\(m\)为奇数时,把\(a_i\)或\(b_i\)最大的放中间......
  • Atcoder ARC100D Equal Cut
    发现是\(3\)个断点且数据范围的\(n\le2\times10^5\),根据2022CSP-SA留下的心理阴影不难想到可以枚举中间的那个点的同时移动左右两个端点。考虑如何移动,已知现在在枚举中间的断点\(i\),则现在被分为了两部分\(1\simi\)和\(i\simn\),因为要使极差最小,那就先可以让每一......
  • Atcoder ABC221G Jumping sequence
    发现这个\((x,y)\)对应的是曼哈顿距离不太好求,那直接逆时针旋转\(45\)度(其实应该还要伸长\(\sqrt{2}\)倍,但是可以当做\(d_i\)也伸长\(\sqrt{2}\)倍不用去管)转化成切比雪夫距离\((x-y,x+y)\)。同时对应的\(4\)个方向在旋转后对应的方向也得到了改变:\(U(-d,d),......
  • AtCoder Beginner Contest 240 D
    D-StrangeBallstag:栈模拟发现自己隔了快半年再做此题看错相同数字的球消失的条件,不是\(k\geq2\)而是\(k=a_i\)电子竞技不需要视力题意:当球\(a_i(1\leqi\leqN)\)有\(a_i\)个一起出现时,这\(a_i\)个球就会消失,问每次放一个球进去,放进去后还剩多少个球?用个......
  • CodeForces - 659B Qualifying Contest (模拟)水
    TimeLimit: 1000MS MemoryLimit: 262144KB 64bitIOFormat: %I64d&%I64uCodeForces-659BQualifyingContestSubmit StatusDescriptionVerysoonBerlandwillholdaSchoolTeamProgrammingOlympiad.Fromeachofthe m Berlandregionsateamoftwopeo......
  • codeforces.com/contest/1553/problem/B
    简单字符串哈希题意给一个字符串s和t,问从s的某个位置开始,向右到某个点后再向左,顺序遍历到的字符形成的字符串可否为t。思路数据只有500,\(O(n^3)\)可过,枚举转折点,然后枚举开头和结尾。代码intn,m,k;ullHash[1010],rHash[1010],p[1010],rp[1010],sum;voidsolve(){ ......
  • AtCoder Beginner Contest 150 E Change a Little Bit
    洛谷传送门AtCoder传送门令\(S_i\getsS_i\oplusT_i\),那么代价中\(D\)变成\(S_i=1\)的\(i\)数量。转化为对所有\(f(S)\)求和,最后答案乘上\(2^n\)。考虑贪心地求\(f(S)\)。肯定是先选择小的\(C_i\),把\(S_i\)变成\(0\)。正确性显然。下面把\(C_i\)从大到......
  • AtCoder Beginner Contest 281 Ex Alchemy
    洛谷传送门AtCoder传送门考虑设\(f_i\)为\(i\)的答案,那么:\[f_i=[x_i](1+x)^A\prod\limits_{j=2}^{i-1}(1+f_jx)\]这个东西其实是可以分治FFT的。具体地,设分治区间为\([l,r]\),要求一个\(r-l+1\)次多项式\(\prod\limits_{i=l}^r(1+f_ix)\)。......