算法第一次作業

問題0:求幾何圖形的個數<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

問題描述

設有n*m個方格的棋盤(1<=m,n<=100),求出該棋盤中包含多少個正方形、多少個長方形(不包括正方形)。

  例如:當n=3m=2  

  正方形的個數有8個;即邊長爲1的正方形有6個;邊長爲2的正方形有2個。

  長方形的個數有10個;即2*1的長方形有4個;1*2的長方形有3個;3*1的長方形有2個;3*2的年長方形有1個。

  程序要求:輸入nm,輸出正方形的個數和長方形的個數。

例如: 輸入:3 2      輸出: 8  10

  運行示例:

  input n,m:1 1        output: 1 0

  input n,m:4 5         output:40 110

  input n,m:10 10        output:385 2640

  input n,m:30 20        output:4970 92680

  input n,m:50 50        output:42925 1582700

 

問題分析

我們可以把棋盤放到座標系中考慮。如圖所示,爲3*2的方格。在座標系中,每兩點即可表示一個矩形。如(2,1(0,0)表示1*2的矩形。這裏我們規定:用右上角的點A(x1,y1)和左下角的點B(x2,y2)來確定一個矩形,並且保證x2<x1,y2<y1.x1-x2=y1-y2A,B確定的是一個正方形,否則是一個領邊不等的長方形。

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

 


數據結構

矩形的數據結構Rectangle=(P,R)

其中:P={0,1,2……n}   n=max(M,N)

      R={A,B}

      A={<x1,y1>|1<=x1<=M,1<=y1<=N}

      B={<x2,y2>|0<=x2<=x1,0<=y2<=y1 }

正方形的數據結構Square=(P,R)

其中P={0,1,2……n}   n=max(M,N)

      R={A,B}

      A={<x1,y1>|1<=x1<=M,1<=y1<=N}

      B={<x2,y2>|0<=x2<=x1,0<=y2<=y1,x1-x2=y1-y2 }

長方形(不包括正方形)的數據結構Oblong=P,R

其中P={0,1,2……n}   n=max(M,N)

      R={A,B}

      A={<x1,y1>|1<=x1<=M,1<=y1<=N}

      B={<x2,y2>|0<=x2<=x1,0<=y2<=y1,x1-x2<>y1-y2 }

 

上述數據結構中,P爲從0MN的自然數集,RAB兩點的關係。AB兩點滿足上面定義中的要求。

 

 

算法分析

正方形個數+長方形個數=所有矩形的個數。算出正方形和矩形的個數,即可得長方形的個數。我們先確定點A(x1,y1) 1<=x1<=M,1<=y1<=N然後再確定點B(x2,y2) 0<=x2<=x1,0<=y2<=y1 x1-x2=y1-y2時即爲正方形。其流程圖如下

 

C程序清單

main()

{

    int m,n;

    int i,j;

    int x,y;

    long int square=0,oblong=0;

 

    printf("M,N=/n");

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

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

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

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

                for(y=0;y<j;y++)

                    {

                        if((i-x)==(j-y))

                            square++;

                                          else oblong++;

                    }

    printf("%6ld,%6ld",square,oblong);

    getch();

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

問題一:求最大數

問題描述:

設有n個正整數(n<=20),將它們聯成一排,組成一個最大的多位數。

  例如:n=3時,3個整數13312343聯接成的最大整數爲:34331213

  又如:n=4時,4個整數7134246聯接成的最大整數爲7424613

程序輸入:n

 程序輸出:n個數聯接成的多位數。

 

問題分析:

此題猛一看很簡單,其實不然。看第一遍時,偶以爲就是把數按由大到小排列,然後合併。但給出的例子“n=4時,4個整數7134246聯接成的最大整數爲<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />7424613否定了偶的猜測。偶又以爲是比較第一位數的大小,如果第一位數相同就比較第二位,以此類推。但自己給出的一組數“743421又否定鳥偶的猜測。要是按偶的算法,得出來的是742431,而正確結果應該是744231。所以此題的關鍵是,當一個數是另一個數的前半部分的情況。如果碰到這種情況,我們可以截去長數前面相同的部分然後再比較如果又相同又要截去又要比較如果又相同又要截去又要比較……所以這又是一個遞歸問題.

 

數據結構

 

算法分析

我們可以用字符串的形式存放數組,然後“比較”字符串的大小,把大的放在前面。其兩個字符串s1s2具體的比較規則如下:

1.  先判斷第一個字符,哪個大哪個就是“大數”。

2.  如果第一個字符相等,就判斷第二個字符。以此類推。

3.  如果其中一個字符串所有的字符都比較完了還沒分出大小(即其中一個字符串是另一個字符串的一部分),那麼就把長的字符串截去前面相同的部分。然後把剩下的和原來短的那個字符串比較。

 

 

 

 

 

c程序清單

#include <string.h>

#include <stdio.h>

#include <conio.h>

 

#define min(x,y)    ((x)>(y)?(y):(x))

 

int NewStrcmp(char *pszNum1,char *pszNum2)

{

    unsigned int nMinLen;

    int nResult;

    if(strlen(pszNum1)==0)

        return -1;

    if(strlen(pszNum2)==0)

        return 1;

 

    nMinLen=min(strlen(pszNum1),strlen(pszNum2));

/*如果一個字符串是第二個字符串的前綴的話,則將長串與第一個字符串相同的部分*/

/*截去,將剩下的繼續比較,當出現有字串長度爲0的時候特殊處理*/

 

    if((nResult=strncmp(pszNum1,pszNum2,nMinLen))==0)

    {

        if(nMinLen==strlen(pszNum1))

        {

            return NewStrcmp(pszNum1,pszNum2+nMinLen);

        }

        else

        {

            return NewStrcmp(pszNum1+nMinLen,pszNum2);

        }

    }

    else

    {

        return nResult;

    }

 

}

 

main()

{

    unsigned int i,j,n;

    char *pszNum[20];

 

    printf("/N(N<20):");

    scanf("%d",&n);

 

    printf("input %d number/n",n);

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

    {

        pszNum[i]=calloc(5,sizeof(char *));

        gets(pszNum[i]);

    }

    putchar('/n');

    /*用冒泡排序*/

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

    {

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

        {

            if(NewStrcmp(pszNum[j],pszNum[j+1])<0)

            {

                char *pTmp;

                pTmp=pszNum[j];

                pszNum[j]=pszNum[j+1];

                pszNum[j+1]=pTmp;

            }

        }

    }

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

        printf("%s",pszNum[i]);

    printf("/n");

    getch();

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

問題2:揹包問題

問題描述

設有一個揹包,可以放入的重量爲S。現有N件物品,重量分別爲W1,W2,…WNWi(1<=I<=N)均爲正整數,從n件物品中挑選若干件,使得放入揹包的重量之和正好爲S

測試數據:

 The number of object: 3 

 Total weight=7

 Weight of each object:9 6 2

 Output:

 Not find

 The number of object: 5

 Total weight=10

 Wweight of each object:1 6 2 7 5

 Output:

 Number: 1    Weight: 1

 Number: 3    Weight: 2

 Number: 4     Weight:7

 

問題分析

A1,A2……An爲取出的滿足條件的n件物品,即A1+A2+……+An=S.則有A1+A2+……A(n-1)=S-An. 也就是說,若揹包可放入的重量爲S-An,N-1件物品中可取出n-1件物品A1,A2……A(n-1)滿足要求。以此類推,必有當揹包可放入的重量爲S-An+A(n-1)+……A2)時,從N-n+1件物品中可取出A1滿足要求。分析得,此問題可用遞歸求解。

 

 

算法分析

可構造一遞歸函數Beibao(s,n)完成從n個數中取出若干個使其和等於s的任務。其中n個數存放在w[n]中。若w[n]能取出,則必有Beibao(s-w[n],n-a)有解;否則跳過w[n],計算Beibao(s,n-1);

 

 

 

 

 

 

c程序清單

#include<stdio.h>

 

 

int w[100];

main()

{

    int S,N;

    int i;

    printf("beibao ke zhuang zhongliang:");

    scanf("%d",&S);

    printf("/n");

    printf("wupin geshu:");

    scanf("%d",&N);

    printf("/n");

    printf("input wupin zhongliang w[1]...w[N]:/n");

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

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

    if(Beibao(S,N))

        printf("OK!/n");

    else

        printf("NO!/n");

    getch();

}

 

int Beibao(int s,int n)

{

    if(s==0)      /*s0時,返回1 */

        return 1;

    if(s<0||(s>0&&n<1)) /* 當裝入的物品重量大於s,或者物品裝完還沒裝滿時,*/

        return 0;       /*返回0,即無解*/

    if(Beibao(s-w[n],n-1))  /*當且僅當n-1個物品裝入容量爲s-w[n]的揹包有解時, */

    {                     /*可以裝入w[n],並返回1 */

        printf("%4d",w[n]);

            return 1;

    }

    return Beibao(s,n-1);   /* 運行到這就說明n-1個物品裝入容量爲s-w[n]的揹包無解。*/

}                       /* 此時跳過w[n],計算把n-1個物品裝入容量爲s的情況*/

                       

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章