藍橋杯 試題 歷屆試題 螞蟻感冒

問題描述
  長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

  • 第一個數據爲正值( 第一隻感冒的螞蟻頭朝右 )
首先看第一隻感冒的螞蟻的右端:由於咱們考慮的是螞蟻相遇後仍按原方向移動,那麼對於第一隻感冒螞蟻右側方向也向右的螞蟻不會被感染( 畫×的螞蟻)
而右側方向向左的螞蟻會與第一隻螞蟻相遇而感冒。
以後再看左側:左側的螞蟻這時可能會被右側畫√的螞蟻感染。但左側方向也向左的不會被感染(速度相同,追不上),只有左側方向向右的螞蟻會被感染。
  • 再看第一個數據爲負值(即第一隻感冒的螞蟻頭朝左)

首先看左側螞蟻,思路相同,左側方向向右的螞蟻最終會被感染,而向左的不會。設計

以後看右側,右側螞蟻可能會被左側畫√的螞蟻感染,但只有右側方向向左的。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;
}
相關文章
相關標籤/搜索