Gym - 100543D Wheels 模拟|BFS|签到

39 篇文章 0 订阅
29 篇文章 0 订阅

题目链接:点击打开链接

题目大意:给你n个齿轮的坐标以及半径,假设第一个齿轮的转速为1,顺时针转,求当施加力量使得第一个齿轮转动时,其他齿轮是否转动以及转速转动情况。


题目思路:利用BFS从第一个齿轮开始遍历,把与他相邻的齿轮加进队列然后顺着往下扫描即可,暴力模拟可做。

AC代码:

/*
2017年8月26日19:59:41
Gym-100543D 
AC
*/
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector> 
using namespace std;
const int maxn=1010;
const double eps=1e-8;
int n;
struct Point{
	int x,y,r;//坐标 半径 
	int fz,fm;//分子分母 
	bool spin;//是否旋转的标志 
	bool dir;//true: clockwise  false conterclockwise
	void init(){//初始化 
		x=y=r=fz=fm=0;
		spin=false;
	}
}a[maxn];

bool vis[maxn];//访问标记 
/*用来约分*/ 
int gcd(int x, int y)
{
	return y ? gcd(y, x % y) : x;
}
/*返回两点之间的距离*/ 
double dis(int x1,int y1,int x2,int y2){
	return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

void bfs(){
	memset(vis,false,sizeof(vis));
	Point p,p1;
	queue<Point> q;
	/*把齿轮一加入队列*/ 
	p.x=a[1].x;
	p.y=a[1].y;
	p.r=a[1].r;
	p.fz=1;
	p.fm=1;
	p.spin=true;
	p.dir=true;
	vis[1]=true;
	/*并且更新齿轮一的转速以及方向*/ 
	a[1].fz=1;
	a[1].fm=1;
	a[1].spin=true;
	a[1].dir=true;
	/*加入队列*/ 
	q.push(p);
	while(!q.empty()){
		p1=q.front();
		q.pop();
		for(int i=1;i<=n;i++){
			if(!vis[i]){
				int x1,x2,y1,y2;
				x1=p1.x;
				x2=a[i].x;
				y1=p1.y;
				y2=a[i].y;
				if(abs(dis(x1,y1,x2,y2)-(double)(p1.r+a[i].r)<=eps)){
					/*如果这两个圆相切,将这个点加入队列*/ 
					p.x=a[i].x;
					p.y=a[i].y;
					p.r=a[i].r;
					p.spin=true;
					p.dir=!(p1.dir);//该圆转的方向与启动的圆方向相反
					//算出转速并且约分 简单的高中物理  r1/r2=v1/v2 
					int fz,fm;
					fz=p1.fz*p1.r;
					fm=p1.fm*p.r;
					int g=gcd(fz,fm);
					if(g!=1) fz/=g,fm/=g;
					p.fz=fz;
					p.fm=fm;
					vis[i]=true;//访问标记置为1
					//更新这个齿轮的信息 
					a[i].spin=p.spin;
					a[i].dir=p.dir;
					a[i].fz=p.fz;
					a[i].fm=p.fm;
					//进队列 
					q.push(p);
					
				} 
			}
		}
	}
}

int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		//对每个点进行初始化 
		for(int i=1;i<=n;i++) a[i].init(); 
		for(int i=1;i<=n;i++){
			scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].r);
		}
		bfs();
		for(int i=1;i<=n;i++){
			if(a[i].spin&&a[i].fm){//如果该点能够转动 并且有转速 
				if(a[i].fm==1){
					printf("%d ",a[i].fz);
					if(a[i].dir==1){
						printf("clockwise\n");
					}
					else{
						printf("counterclockwise\n");
					}
				}
				else{
					printf("%d/%d ",a[i].fz,a[i].fm);
					if(a[i].dir==1){
						printf("clockwise\n");
					}
					else{
						printf("counterclockwise\n");
					}
				}	 
			} 
			else printf("not moving\n");
			
		}
	}
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值