1. 程式人生 > 實用技巧 >[洛谷P3843] TJOI2007 迷路

[洛谷P3843] TJOI2007 迷路

題目背景

小 A 和小 B 在一個二維空間中迷路了,每個人在這個空間中都按照自己特定的路線行

走,由於他們的路線都是週期性的,因此你可以把這種路線理解為一種“軌道”:即一條封

閉的路線,路線的終點和起點重合,這樣才能“週期”的行走。

問題描述

兩個人行走的速度都是每秒一個單位距離,而且他們的路線都是平行於座標軸的。基於

此,如果兩個人無限的走下去,我們想知道他們每一秒相離最近的距離。(我們只考慮兩人

在每秒行走後相離的距離,不考慮他們在這 1 秒內某個時刻的距離)

輸入格式

輸入檔案中有兩個相似的部分,分別描述小 A 和小 B 的行走軌道。在每一個部分中的

第一行有三個整數,sx、sy 和 m,前兩個整數表示其初始位置,第三個整數表示軌道中折線

的數目,以下 m 行,每行有一個整數 d 和一個非空格字元 c,d 和 c 之間用一個空格隔開。

d 表示小 A 或小 B 沿座標的正方向行走的距離,而 c 為’X’或’Y’,表示是 X 座標軸還是 Y

座標軸。輸入資料保證在每一個部分中,我們從起點(sx, sy)開始,執行 m 次行走步驟後,一定能

回到起點,即這個軌道是封閉的。

輸出格式

輸出檔案中只包含一個實數,精確到小數點後兩位。表示能觀測到的兩個人的最近距離,

如果可能在某個時間兩個人到達同一個點,則輸出 0.00。

樣例輸入

0 0 4
-1 Y
-1 X
1 Y
1 X
1 0 4
-1 X
1 Y
1 X
-1 Y

樣例輸出

1.00

資料範圍

100%的資料中,對於任何 m 和 d,有 1 ≤ m, d ≤ 100,軌道的初始座標的絕對值不超

過 2 000。

解析

模擬題,直接走最大公倍數次即可。14分應該是看錯題目了。

程式碼

#include <iostream>
#include <cstdio>
#include <cmath>
#define N 102
#define M 10002
using namespace std;
struct event{
	int d;
	char c;
}a[N],b[N];
int n,xa,ya,ma,da,xb,yb,mb,db,i,j=1,k=1;
double ans;
int gcd(int a,int b)
{
	if(a%b) return gcd(b,a%b);
	return b;
}
double dis(int x1,int y1,int x2,int y2)
{
	return sqrt(1.0*(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int main()
{
	cin>>xa>>ya>>ma;
	for(i=1;i<=ma;i++) cin>>a[i].d>>a[i].c,da+=abs(a[i].d);
	cin>>xb>>yb>>mb;
	for(i=1;i<=mb;i++) cin>>b[i].d>>b[i].c,db+=abs(b[i].d);
	n=da*db/gcd(da,db);
	ans=dis(xa,ya,xb,yb);
	int la=a[1].d,lb=b[1].d;
	for(i=1;i<=n;i++){
		if(la==0) j=j%ma+1,la=a[j].d;
		if(lb==0) k=k%mb+1,lb=b[k].d;
		if(a[j].c=='X'){
			if(la>0) xa++,la--;
			else xa--,la++;
		}
		else{
			if(la>0) ya++,la--;
			else ya--,la++;
		}
		if(b[k].c=='X'){
			if(lb>0) xb++,lb--;
			else xb--,lb++;
		}
		else{
			if(lb>0) yb++,lb--;
			else yb--,lb++;
		}
		ans=min(ans,dis(xa,ya,xb,yb));
	}
	printf("%.2lf\n",ans);
	return 0;
}