牛客练习赛20:D. 最短路2

链接:https://www.nowcoder.com/acm/contest/128/D
来源:牛客网

题目描述

"夏天的风 正暖暖吹过 穿过头发穿过耳朵..."耳机里在哼着这首温岚的《夏天的风》,我以为我能这样听着歌,喝着可乐,在寝室里开着空调打游戏,安静地度过这个35℃的下午....
"叮..!"手机屏幕突然弹出一则提醒,"您下午6、7节的排球课别忘了哦~"
唔...果然美好的梦总是会被现实打碎,只好穿上运动鞋,顶着炙热的阳光,向体育馆走去。
体育老师是一个微胖的中年大叔,他总喜欢在上课之前让我们玩游戏,大概是达到热身效果吧。
这次,他又定下了奇怪的游戏规则,于是我把它出成了一道题目:
假设排球场是个无限大的网格,即对于任意的整数z,都有x=z和y=z的直线存在,同学A(A x,A y)和同学B(B x,B y)站在整点坐标(即A x,A y,B x,B y都是整数)上,这个网格里面,还有另外一条直线H,用Px+Qy=R表示,现在A要走到B所在的位置,他只能沿着网格或者H这条线走,且只能在交点处换路。
求A走到B的最短路长度。

输入描述:

输入的第一行包含一个整数T,表示测试组数。
每个测试用例前面都有一个空白行。
每个测试用例由包含整数Ax,Ay,Bx,By和有理数P,Q,R。

输出描述:

对于每个测试用例输出一个数:表示求A走到B的最短路长度,结果保留三位小数。


感觉这题其实是道水题。。。

就是给你一个矩形,再给你一条直线,你要从矩形的一个顶点走到对面的那个顶点,只能在矩形的边上走或者在直线上走,求最短路。。。

如果直线与矩形没有交点,那么很显然答案就是矩形的长+宽

有交点的话如下图:


就有两种情况:①还是只沿着矩阵边走;②中间经过直线

比一下两种情况哪种更优就行了


#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
double Len1(double x1, double y1, double x2, double y2)
{
	return fabs(x1-x2)+fabs(y1-y2);
}
double Len2(double x1, double y1, double x2, double y2)
{
	return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int Jud(double x, double c, double d)
{
	if(c>=d)
		swap(c, d);
	if(x>=c && x<=d)
		return 1;
	return 0;
}
double px[5], py[5];
int main(void)
{
	int T, cnt, i, j;
	double x1, y1, x2, y2, A, B, C, ans, y, x;
	scanf("%d", &T);
	while(T--)
	{
		cnt = 0;
		scanf("%lf%lf%lf%lf%lf%lf%lf", &x1, &y1, &x2, &y2, &A, &B, &C);
		ans = Len1(x1, y1, x2, y2);
		if(A==0 || B==0)
			printf("%.3f\n", ans);
		else
		{
			y = (C-A*x1)/B;
			if(Jud(y, y1, y2))
				px[++cnt] = x1, py[cnt] = y;
			y = (C-A*x2)/B;
			if(Jud(y, y1, y2))
				px[++cnt] = x2, py[cnt] = y;
			x = (C-B*y1)/A;
			if(Jud(x, x1, x2))
				px[++cnt] = x, py[cnt] = y1;
			x = (C-B*y2)/A;
			if(Jud(x, x1, x2))
				px[++cnt] = x, py[cnt] = y2;
			for(i=1;i<=cnt;i++)
			{
				for(j=1;j<=cnt;j++)
				{
					ans = min(ans, Len1(x1, y1, px[i], py[i])+Len2(px[i], py[i], px[j], py[j])+Len1(px[j], py[j], x2, y2));
					ans = min(ans, Len1(x1, y1, px[j], py[j])+Len2(px[i], py[i], px[j], py[j])+Len1(px[i], py[i], x2, y2));
				}
			}
			printf("%.3f\n", ans);
		}
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值