2020ICPC上海 L-Traveling in the Grid World


2020ICPC上海 L-Traveling in the Grid World

题意

给定一个\(n\times m\)的网格图,你站在起始点\((0,0)\),每次移动可以选择一个点\((x,y)\)走线段到达它且这条线段不能经过其他格点,可以做任意次移动,问到达\((n,m)\)所需的移动距离总和最小为多少。

分析

一个简单的结论:若\(gcd(n,m)=1\),可以直接从\((0,0)\)走到\((n,m)\),否则只需要一次转折即可到达\((n,m)\)。假设转折点为\((x,y)\)那么需要满足\(gcd(x,y)=1\)\(gcd(n-x,m-y)=1\)。暴力枚举\((0,0)\)\((n,m)\)连线附近的点作为转折点计算距离取最小值即可。

Code

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;
const int mod=1e9+7;
const int N=1e5+10;
const int inf=1e9;
int T,n,m;
int xx[]={1,-1,0,0};
int yy[]={0,0,1,-1};
double cal(int x,int y){
	return sqrt(1.0*x*x+1.0*y*y);
}
double gao(int x,int y){
	if(y<0||y>m) return inf;
	if(__gcd(x,y)!=1||__gcd(n-x,m-y)!=1) return inf;
	if(x*m==y*n) return inf;
	return cal(x,y)+cal(n-x,m-y);
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&m);
		double ans=inf;
		if(__gcd(n,m)==1){
			ans=sqrt(1.0*n*n+1.0*m*m);
		}else{
			for(int i=0;i<=n;i++){
				int j=i*m/n;
				ans=min(ans,gao(i,j));
				ans=min(ans,gao(i,j-1));
				ans=min(ans,gao(i,j+1));
			}
		}
		printf("%.9f\n",ans);
	}
	return 0;
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM