The 2024 Sichuan Provincial Collegiate Programming Contest F. Isoball: 2D Version

The 2024 Sichuan Provincial Collegiate Programming Contest F. Isoball: 2D Version

题目链接:

F. Isoball: 2D Version

正经题意:

有一个固定的矩形,一个大小固定的圆沿一个方向运动,问有没有一个时刻圆完全在矩形里。多组数据,其中
1 ≤ T ≤ 104, −106 ≤ x, y, vx , vy lx , ly, rx , ry ≤ 106,1 ≤ r ≤ 106

简而言之:

就是一个球根据一个向量移动,有没有一个时刻能够满足完全在矩形里(这个题意容易懂,没什么好简化的)

思路:

我的思路比较笨,把圆当作一个矩形,因为圆完全在矩形中,其实和以圆心为原点,半径为边长的矩形在矩形中是等价的。
所以我列了3种情况:
1.无法移动
2.x方向向量存在,那么就可以分为两种情况:
[1]将圆的左边移动到和矩形左边共线
[2]将圆的右边移动到和矩形右边共线
3.y方向向量存在,那么就可以分为两种情况:
[1]将圆的上边移动到和矩形上边共线
[2]将圆的下边移动到和矩形下边共线
再根据以上所有情况去考虑是否符合完全包含就可以了。

代码:

代码写的较丑,请见谅

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+27;

void solve(){
	double x,y,r,vx,vy;
	double lx,ly,rx,ry;
	cin>>x>>y>>r>>vx>>vy;
	cin>>lx>>ly>>rx>>ry;
	if(vx == 0 && vy==0){
		if(x+r <= rx && x-r>=lx){
			if(y+r <= ry && y-r >= ly){
				cout<<"Yes"<<endl;
				return ;
			}
		}
		cout<<"No"<<endl;
		return ; 
	}
	if(x+r <= rx && x-r>=lx){
		if(y+r <= ry && y-r >= ly){
			cout<<"Yes"<<endl;
			return ;
		}
	}
	if(vx!=0){
		double lx_01 = x-r,ly_01 = y-r;
		double ry_01 = y+r,rx_01 = x+r;
		if(lx_01 <= lx && vx > 0 || lx_01 >= lx && vx<0){
			double rectation1 =  (lx - lx_01)/vx;
			lx_01 += rectation1*vx;
			ly_01 += rectation1*vy;
			rx_01 += rectation1*vx;
			ry_01 += rectation1*vy;
			if(lx_01>=lx && lx_01 <= rx){
				if(ly_01>=ly && ly_01 <= ry){
					if(rx_01>=lx && rx_01 <= rx){
						if(ry_01>=ly && ry_01 <= ry){
							cout<<"Yes"<<endl;
							return ; 
						}
					}
				}
			}		
		}
		lx_01 = x-r,ly_01 = y-r;
		ry_01 = y+r,rx_01 = x+r;
		if(rx_01 <= rx && vx > 0 || rx_01 >= rx && vx < 0){
			double rectation1 =  (rx - rx_01)/vx;
			lx_01 += rectation1*vx;
			ly_01 += rectation1*vy;
			rx_01 += rectation1*vx;
			ry_01 += rectation1*vy;
			if(lx_01>=lx && lx_01 <= rx){
				if(ly_01>=ly && ly_01 <= ry){
					if(rx_01>=lx && rx_01 <= rx){
						if(ry_01>=ly && ry_01 <= ry){
							cout<<"Yes"<<endl;
							return ; 
						}
					}
				}
			}	
		}
	}
	if(vy!=0){
		double lx_01 = x-r,ly_01 = y-r;
		double ry_01 = y+r,rx_01 = x+r;
		if(ly_01 <= ly && vy > 0 || ly_01 >= ly && vy < 0){
			double rectation1 =  (ly - ly_01)/vy;
			lx_01 += rectation1*vx;
			ly_01 += rectation1*vy;
			rx_01 += rectation1*vx;
			ry_01 += rectation1*vy;
			if(lx_01>=lx && lx_01 <= rx){
				if(ly_01>=ly && ly_01 <= ry){
					if(rx_01>=lx && rx_01 <= rx){
						if(ry_01>=ly && ry_01 <= ry){
							cout<<"Yes"<<endl;
							return ; 
						}
					}
				}
			}	
		}
		lx_01 = x-r,ly_01 = y-r;
		ry_01 = y+r,rx_01 = x+r;
		if(ry_01 <= ry && vy > 0 || ry_01 >= ry && vy < 0){
			double rectation1 =  (ry - ry_01)/vy;
			lx_01 += rectation1*vx;
			ly_01 += rectation1*vy;
			rx_01 += rectation1*vx;
			ry_01 += rectation1*vy;
			if(lx_01>=lx && lx_01 <= rx){
				if(ly_01>=ly && ly_01 <= ry){
					if(rx_01>=lx && rx_01 <= rx){
						if(ry_01>=ly && ry_01 <= ry){
							cout<<"Yes"<<endl;
							return ; 
						}
					}
				}
			}	
		}
	} 
	cout<<"No"<<endl;
	return ;
}

	
int main()
{
	int t;cin>>t;
	while(t--){
		solve();
	}
	return 0;
} 
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值