問題描述
長100釐米的細長直杆子上有n只螞蟻。它們的頭有的朝左,有的朝右。
每隻螞蟻都只能沿着杆子向前爬,速度是1釐米/秒。
當兩隻螞蟻碰面時,它們會同時掉頭往相反的方向爬行。
這些螞蟻中,有1只螞蟻感冒了。而且在和其它螞蟻碰面時,會把感冒傳染給碰到的螞蟻。
請你計算,當全部螞蟻都爬離杆子時,有多少隻螞蟻患上了感冒。
輸入格式
第一行輸入一個整數n (1 < n < 50), 表示螞蟻的總數。
接着的一行是n個用空格分開的整數 Xi (-100 < Xi < 100), Xi的絕對值,表示螞蟻離開杆子左邊端點的距離。正值表示頭朝右,負值表示頭朝左,數據中不會出現0值,也不會出現兩隻螞蟻佔用同一位置。其中,第一個數據表明的螞蟻感冒了。
輸出格式
要求輸出1個整數,表示最後感冒螞蟻的數目。
樣例輸入
3
5 -2 8
樣例輸出
1
樣例輸入
5
-10 8 -20 12 25
樣例輸出
3
這一題與 POJ No.1852(Ant)思路類似,首先來看一下POJ的題目:
題目描述:
由於題目難抄,因此直接用了https://blog.csdn.net/qq_43751506/article/details/105836389這位朋友的圖片,我也是在一塊兒來挑戰程序設計這本書中看到這一題的。
若是暴力搜索全部螞蟻向左或向右兩種可能,則有2^n複雜度,指數爆炸。
首先考慮最短期:全部的螞蟻應該都朝向離本身近的一端爬行,即以左端爲座標0點,則[ 0, L/2 ] 的螞蟻應該朝左爬, (L/2, L ] 的螞蟻應該朝右爬。這時沒有螞蟻相遇的狀況。
接下來思考最長時間。
若是直接考慮一個螞蟻不間斷的相遇,改變本身的方向...會讓問題變得很複雜。實際上,咱們考慮的是最長時間,而不是某個螞蟻的狀態。
若是忽略了螞蟻之間的區別,能夠認爲兩個螞蟻相遇時是保持原方向交錯而過。
這樣思考問題就簡單多了:最長時間即螞蟻離端點的最遠距離。
主要代碼:
//輸入
int n,L;
int x[Max_N];//保存螞蟻的位置
void solve()
{
int Min_T = 0, Max_T = 0;
for(int i=0; i<n; i++)
{
Min_T = max( Min_T, min(x[i],L-x[i])); //計算最短期
Max_T = max( Max_T, max(x[i],L-x[i]));//計算最長時間
}
printf("%d %d\n",Min_T,Max_T);
}
在回頭看這道藍橋杯題:當螞蟻相遇時,一樣能夠視爲沒有改變方向交錯而過,只是和感冒的螞蟻相遇後另外一隻也會感冒。spa
考慮兩種狀況:.net
首先看第一隻感冒的螞蟻的右端:由於咱們考慮的是螞蟻相遇後仍按原方向移動,那麼對於第一隻感冒螞蟻右側方向也向右的螞蟻不會被感染( 畫×的螞蟻)
而右側方向向左的螞蟻會與第一隻螞蟻相遇而感冒。
以後再看左側:左側的螞蟻這時可能會被右側畫√的螞蟻感染。但左側方向也向左的不會被感染(速度相同,追不上),只有左側方向向右的螞蟻會被感染。
![](http://static.javashuo.com/static/loading.gif)
首先看左側螞蟻,思路相同,左側方向向右的螞蟻最終會被感染,而向左的不會。設計
以後看右側,右側螞蟻可能會被左側畫√的螞蟻感染,但只有右側方向向左的。code
綜合這兩張圖能夠很發現:在第一隻感冒螞蟻左側方向向右的會被感染;右側方向向左的會被感染。因此代碼就很是簡單。
實現代碼:
#include<cstdio>
//其實只要求在感冒位置左邊方向向右;右邊方向向左的個數就能夠了
const int Max_N = 50;
int n;
int x[Max_N+1];// 0:沒有螞蟻 -1:向左 1:向右
int ant; //感冒螞蟻的位置
void solve()
{
int res = 0;
for(int i=1; i<ant; i++){//左邊 向右
if( x[i]==1 ) res++;
}
for(int i=ant+1; i<=100; i++){//右邊 向左
if( x[i]==-1 ) res++;
}
printf("%d\n",res+1);//加上原來的第一隻感冒的螞蟻
}
int main()
{
scanf("%d",&n);
int a;
scanf("%d",&a);
ant = a>0 ? a : -a;//第一個位置是感冒的位置
while( --n )
{//剩下的n-1個
scanf("%d",&a);
if( a>0 ) x[a] = 1;//向右
else x[-a] = -1; //向左
}
solve();
return 0;
}