1615: [Usaco2008 Mar]The Loathesome Hay Baler麻煩的乾草打包機
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 956 Solved: 391
[Submit][Status][Discuss]
Description
Farmer John新買的乾草打包機的內部結構大概算世界上最混亂的了,它不象普通的機器一樣有明確的內部傳動裝置,而是,N (2 <= N <= 1050)個齒輪互相作用,每個齒輪都可能驅動着多個齒輪。 FJ記錄了對於每個齒輪i,記錄了它的3個參數:X_i,Y_i表示齒輪中心的位置座標(-5000 <= X_i <= 5000; -5000 <= Y_i <= 5000);R_i表示該齒輪的半徑(3 <= R_i <= 800)。驅動齒輪的位置爲0,0,並且FJ也知道最終的工作齒輪位於X_t,Y_t。 驅動齒輪順時針轉動,轉速爲10,000轉/小時。你的任務是,確定傳動序列中所有齒輪的轉速。傳動序列的定義爲,能量由驅動齒輪傳送到工作齒輪的過程中用到的所有齒輪的集合。對能量傳送無意義的齒輪都應當被忽略。在一個半徑爲Rd,轉速爲S轉/每小時的齒輪的帶動下,與它相接的半徑爲Rx的齒輪的轉速將爲-S*Rd/Rx轉/小時。S前的負號的意思是,一個齒輪帶動的另一個齒輪的轉向會與它的轉向相反。 FJ只對整個傳動序列中所有齒輪速度的絕對值之和感興趣,你的任務也就相應轉化成求這個值。機器中除了驅動齒輪以外的所有齒輪都被另外某個齒輪帶動,並且不會出現2個不同的齒輪帶動同一個齒輪的情況。 相信你能輕易地寫個程序來完成這些計算:)
Input
* 第1行: 3個用空格隔開的整數:N,X_t,Y_t
* 第2..N+1行: 第i+1描述了齒輪i的位置及半徑:X_i,Y_i,以及R_i
Output
* 第1行: 輸出所有在傳動中起到作用的齒輪轉速的絕對值,包括驅動齒輪和 工作齒輪。只需要輸出答案的整數部分
Sample Input
0 0 10
0 30 20
32 54 20
-40 30 20
機器裏一共有4個齒輪,位於0,0的是半徑爲10的驅動齒輪,它帶動了位於
0,30的,半徑爲20的某個齒輪。這個齒輪又間接帶動了位於32,54,半徑爲20的
工作齒輪,以及一個位於-40,30,半徑同樣爲20的冗餘的齒輪。
Sample Output
HINT
輸出說明:
齒輪 位置 半徑 轉速
1 (0,0) 10 10,000
2 (0,30) 20 -5,000
3 (32,54) 20 5,000
------
齒輪轉速絕對值之和:20,000
題解:第一反應就是BFS。。。
然後題目中說了“不會出現2個不同的齒輪帶動同一個齒輪的情況”,因此可以用搜索。。。
然後BFS的過程中滿足:sqr(x[i]-x[j])+sqr(y[i]-y[j])==sqr(r[i]+r[j]); 即可
速度公式題目告訴了。。。取絕對值加上就好。。。
代碼:
#include<cstdio>
#include<queue>
const int maxn=1051;
using namespace std;
int x[maxn],y[maxn],r[maxn];
double v[maxn],ans[maxn];
int tx,ty,t,n,now;
queue<int> q;
int sqr(int x){return x*x;}
bool ok(int i,int j){return sqr(x[i]-x[j])+sqr(y[i]-y[j])==sqr(r[i]+r[j]);}
int main()
{
scanf("%d%d%d",&n,&tx,&ty); //讀入數量、終止節點的座標
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&x[i],&y[i],&r[i]); //讀入每個齒輪的座標,半徑
if(x[i]==tx&&y[i]==ty)t=i; //記錄結束節點在數組裏的位置,方便最後輸出
if(x[i]==0&&y[i]==0) //對開始節點進行處理
{
q.push(i); //將開始節點放入隊列
v[i]=10000;
ans[i]=10000; //開始的時候速度絕對值之和和單個i的速度都爲10000;
}
}
while(!q.empty())
{
now=q.front(); //將now指向隊列的首個數
q.pop();
for(int i=1;i<=n;i++)
if(!ans[i]&&ok(i,now)) //滿足題解裏說的條件
{
v[i]=v[now]*r[now]/r[i];
ans[i]=ans[now]+v[i]; //公式
q.push(i); //再進隊列
}
}
printf("%d",(int)ans[t]); //輸出答案,記得要向下取整(不是四捨五入,很多題解都說成四捨五入。。。int是向下取整。。。)
return 0;
}