@himnouth
2022-08-08T06:56:31.000000Z
字数 1575
阅读 323
题解
题目链接:https://atcoder.jp/contests/abc259/tasks/abc259_d
现给定个在平面坐标系中的圆,第个圆圆心坐标为,半径为。又给定两个坐标及,试求出可否从出发且只经过给定圆的圆周可否到达点。
对于每个测试点,第一行输入,第二行输入,其后行,每行输入。
如果能到达,输出"";否则输出""。
40 -2 3 30 0 22 0 22 3 1-3 3 3
Yes
30 1 0 30 0 10 0 20 0 3
No
原图如下:
以下为从点至点的走法之一。
1. 从点经过给定的第一个圆可移动到点。
2. 从点经过给定的第二个圆可移动到点。
3. 从点经过给定的第三个圆可移动到点。
原图如下:
由图可知:
不可在只经过圆周的情况下从点移动至点。
本题使用图论算法求解。
可将所有圆编号并视为一个点,若两个圆可相互到达,即可视为两点间存在一条边,以样例为例,则原图可化为一无向图,如下:
原问题可变化为:求点与点是否联通。
以上问题可使用深度优先搜索算法进行求解。
综上,原问题解法为:先将原图转化为有向图后使用深度优先搜索算法判断起点与终点是否连通即可。
以上算法代码实现如下:
#include<bits/stdc++.h>using namespace std;using ll=long long;ll b,k,sx,sy,gx,gy;ll ask(){ll ans=k*(abs(sx-gx)+abs(sy-gy));ll sy_2=sy-sy%b,gy_2=gy-gy%b,sx_2=sx-sx%b,gx_2=gx-gx%b;for(auto [x_1,y_1]:{array{sx,sy_2},{sx,sy_2+b},{sx_2+b,sy},{sx_2,sy}}){for(auto [x_2,y_2]:{array{gx,gy_2},{gx,gy_2+b},{gx_2+b,gy},{gx_2,gy}}){ll res;if(x_1%b==0&&x_2%b==0&&y_1/b==y_2/b){int r=y_2%b+y_1%b;res=min((ll)abs(y_2-y_1)+(ll)abs(x_2-x_1)*k,(ll)min(abs(x_2-x_1)+r,(ll)abs(x_2-x_1)+2*b-r));}else if(y_1%b==0&&y_2%b==0&&x_1/b==x_2/b){int r=x_2%b+x_1%b;res=min((ll)abs(x_2-x_1)+(ll)abs(y_2-y_1)*k,(ll)min(abs(y_2-y_1)+r,(ll)abs(y_2-y_1)+2*b-r));}else{res=(ll)abs(x_2-x_1)+(ll)abs(y_2-y_1);}res+=k*(abs(x_1-sx)+abs(y_1-sy)+abs(x_2-gx)+abs(y_2-gy));ans=min(ans,res);}}return ans;}int main(){int T;cin>>T;while(T--){scanf("%lld%lld%lld%lld%lld%lld",&b,&k,&sx,&sy,&gx,&gy);printf("%lld\n",ask());}return 0;}