C語言程序設計100例之(19):歡樂的跳

例19   歡樂的跳

題目描述編程

一個n個元素的整數數組,若是數組兩個連續元素之間差的絕對值包括了[1,n-1]之間的全部整數,則稱之符合「歡樂的跳」,如數組1 4 2 3符合「歡樂的跳」,由於差的絕對值分別爲:3,2,1。數組

給定一個數組,你的任務是判斷該數組是否符合「歡樂的跳」。測試

輸入格式spa

每組測試數據第一行以一個整數n(1≤n≤1000)開始,接下來n個空格隔開的整數。開發

輸出格式hash

對於每組測試數據,輸出一行若該數組符合「歡樂的跳」則輸出"Jolly",不然輸出"Not jolly"。io

輸入樣例 #1 循環

4 1 4 2 3程序

輸出樣例 #1 方法

Jolly

輸入樣例 #2

5 1 4 2 -1 6

輸出樣例 #2

Not jolly

        (1)編程思路。

        爲了判斷數組兩個連續元素之間差的絕對值是否包括了[1,n-1]之間的全部整數,定義一個數組int hash[1001],其中hash[i]=0表示整數i未出現,hash[i]=1表示整數i出現過。初始時,hash數組的所有元素值均爲0。

        對n個元素的數組a,用循環for (i=1;i<n;i++)對數組中連續兩個元素的差的絕對值d(d=abs(a[i]-a[i-1]))進行處理。若差的絕對值d小於n,則置hash[d]=1,表示整數d出現了。

        以後,判斷數組hash的狀況,若數組元素hash[1]~hash[n-1]的值全爲1,則表示數組a中兩個連續元素之間差的絕對值包括了[1,n-1]之間的全部整數。

        (2)源程序。

#include <stdio.h>

#include <math.h>

int main()

{

    int hash[1001]={0},a[1001],n,i,d;

    scanf("%d",&n);

    for (i=0;i<n;i++)

        scanf("%d",&a[i]);

    for (i=1;i<n;i++)

    {

        d=abs(a[i]-a[i-1]);

        if (d<=n-1) hash[d]=1;

    }

    for (i=1;i<=n-1;i++)

        if (hash[i]==0) break;

    if (i<n)

                   printf("Not jolly\n");

    else

                   printf("Jolly\n");

    return 0;

}

習題19

19-1  校門外的樹

        本題選自洛谷題庫 (https://www.luogu.org/problem/P1047)

題目描述

某校大門外長度爲L的馬路上有一排樹,每兩棵相鄰的樹之間的間隔都是1米。咱們能夠把馬路當作一個數軸,馬路的一端在數軸0的位置,另外一端在L的位置;數軸上的每一個整數點,即0,1,2,…,L,都種有一棵樹。

因爲馬路上有一些區域要用來建地鐵。這些區域用它們在數軸上的起始點和終止點表示。已知任一區域的起始點和終止點的座標都是整數,區域之間可能有重合的部分。如今要把這些區域中的樹(包括區域端點處的兩棵樹)移走。你的任務是計算將這些樹都移走後,馬路上還有多少棵樹。

輸入格式

第一行有2個整數L((1≤L≤10000)和 M(1≤M≤100),L表明馬路的長度,M表明區域的數目,L和M之間用一個空格隔開。

接下來的M行每行包含2個不一樣的整數,用一個空格隔開,表示一個區域的起始點和終止點的座標。

輸出格式

1個整數,表示馬路上剩餘的樹的數目。

輸入樣例

500 3

150 300

100 200

470 471

輸出樣例

298

        (1)編程思路。

        定義數組int f[10001],其中f[i]=1表示座標爲i的位置有一棵樹,f[i]=0表示座標爲i的位置的樹被移走了。初始時,數組的元素f[0]~f[l]所有置爲1,表示長度爲L的馬路上每間隔1米有一棵樹。

        每輸入一組區域的起始點和終止點的座標begin和end,就將f[begin]~f[end]之間的數組元素的值修改成0,表示樹被移走了。

        最後,統計數組f中值爲1的元素的個數,就是馬路上剩餘的樹的數目。

        (2)源程序。

#include <stdio.h>

int main()

{

    int l,m,begin,end,i,cnt;

    int f[10001];

    scanf("%d%d",&l,&m);

    for (i=0;i<=l;i++)

        f[i]=1;

    while (m--)

    {

        scanf("%d%d",&begin,&end);

        for (i=begin;i<=end;i++)

            f[i]=0;

    }

    cnt=0;

    for (i=0;i<=l;i++)

    {

       if (f[i]==1)

          cnt++;

    }

    printf("%d\n",cnt);

    return 0;

}

19-2  校門外的樹(加強版)

        本題選自洛谷題庫 (https://www.luogu.org/problem/P1276)

題目描述

校門外馬路上原本從編號0到L,每一編號的位置都有1棵樹。有砍樹者每次從編號A到B處連續砍掉每1棵樹,就連樹苗也不放過(記 0 A B ,含A和B);幸運的是還有植樹者每次從編號C到D 中凡是空穴(樹被砍且還沒種上樹苗或樹苗又被砍掉)的地方都補種上樹苗(記 1 C D,含C和D);問最終校門外留下的樹苗多少棵?植樹者種上又被砍掉的樹苗有多少棵?

輸入格式

第一行L和N,表示校園外原來有L+1棵樹,並有N次砍樹或種樹的操做。

如下N行,砍樹或植樹的標記和範圍,每行3個整數。

L(1 <= L <= 10000)和 N(1 <= N <= 100)

輸出格式

共兩行。第1行校門外留下的樹苗數目,第2行種上又被拔掉的樹苗數目。

輸入樣例

10 3

0 2 6

1 1 8

0 5 7

輸出樣例

3

2

        (1)編程思路。

        本題思路與上題類同。一樣定義數組int f[10001],其中f[i]=1表示座標爲i的位置有一棵樹,f[i]=2表示座標爲i的位置補種了一顆樹苗,f[i]=0表示座標爲i的位置的樹或樹苗被移走了。初始時,數組的元素f[0]~f[l]所有置爲1,表示長度爲L的馬路上每間隔1米有一棵樹。

        程序中根據砍樹或種樹的操做對數組f的相應元素進行處理。具體見源程序。

       (2)源程序。

#include <stdio.h>

int main()

{

    int l,n,m,begin,end,i,cnt1,cnt2;

    int f[10001];

    scanf("%d%d",&l,&n);

    for (i=0;i<=l;i++)

        f[i]=1;       // 初始爲一棵樹

    cnt2=0;          // 種上又被砍掉的樹苗數

    while (n--)

    {

        scanf("%d%d%d",&m,&begin,&end);

        if (m==0)    // 砍樹或樹苗

        {

            for (i=begin;i<=end;i++)

            {

                if (f[i]==2)  cnt2++;   // 樹苗被砍掉了

                f[i]=0;

            }

        }

        else        // 種樹苗

        {

             for (i=begin;i<=end;i++)

                 if (f[i]==0)

                    f[i]=2;

        }

    }

    cnt1=0;         // 留下的樹苗數

    for (i=0;i<=l;i++)

    {

       if (f[i]==2)

          cnt1++;

    }

    printf("%d\n%d\n",cnt1,cnt2);

    return 0;

}

19-3  珠心算測驗

題目描述

珠心算是一種經過在腦中模擬算盤變化來完成快速運算的一種計算技術。珠心算訓練,既可以開發智力,又可以爲平常生活帶來不少便利,於是在不少學校獲得普及。

某學校的珠心算老師採用一種快速考察珠心算加法能力的測驗方法。他隨機生成一個正整數集合,集合中的數各不相同,而後要求學生回答:其中有多少個數,剛好等於集合中另外兩個(不一樣的)數之和?

最近老師出了一些測驗題,請你幫忙求出答案。

輸入格式

共兩行,第一行包含一個整數n,表示測試題中給出的正整數個數。

第二行有n個正整數,每兩個正整數之間用一個空格隔開,表示測試題中給出的正整數。

輸出格式

一個整數,表示測驗題答案。

輸入樣例

4

1 2 3 4

輸出樣例

2

說明/提示

【樣例說明】

由1+2=3,1+3=4,故知足測試要求的答案爲2。

注意,加數和被加數必須是集合中的兩個不一樣的數。

        (1)編程思路。

        爲了判斷集合中有多少個數剛好等於集合中另外兩個(不一樣的)數之和,定義一個數組int hash[10001],其中hash[i]=0表示整數i做爲和值未出現,hash[i]=1表示整數i做爲和值第1次出現了,hash[i]=2表示整數i做爲和值不止1次出現了,只能算一次。初始時,hash數組中,屬於集合元素的hash數組相應元素值置1,其他非集合元素的相應hash元素值均爲0。

         用二重循環

                    for (i=0;i<n-1;i++)

                        for (j=i+1;j<n;j++)

        對集合中任意兩個不一樣元素的和值t(t=num[i]+num[j])進行處理。若和值t的對應的hash[t]等於1,表示集合中存在元素t爲另外兩個不一樣元素的和,計數,同時置hash[t]=2,以免下次再出現和值t產生重複計數。

        (2)源程序。

#include <stdio.h>

int main()

{

    int n,i,j,t,cnt=0,num[100];

    int hash[10001]={0};

    scanf("%d",&n);  

    for (i=0;i<n;i++)

         {

                   scanf("%d",&num[i]);

                   hash[num[i]]=1;

         }

         for (i=0;i<n-1;i++)

                   for (j=i+1;j<n;j++)

                   {

                            t=num[i]+num[j];

                            if (t<=10000 && hash[t]==1)

                            {       

                                     cnt++;

                                     hash[t]=2;  // 注意:1+4和2+3也算重複,需去掉

                            }

                   }

         printf("%d\n",cnt);

         return 0;

}

相關文章
相關標籤/搜索