演算法設計幾個經典思維題目

果7發表於2013-10-24

演算法課和.net是最有意思的兩門課,一定得好好聽!


1.求n!尾數0的個數?(n>=10000)


開始,我想的是dp的方法,但也說不上怎麼dp。仔細想一下0是如何產生的呢?

是2*5產生的,我們需要統計2和5的個數,不用想也清楚,2的個數肯定大於5的

個數2,4=2*2,6=2*3,8=2*2*2.因此我們只需要統計5的個數即可。而如何統計

5的個數也成為一個眾說紛紜的問題。其實可以達到O(1)的複雜度,

n!中包含5的個數為 n/5+n/25+n/125+n/625+........

我們可以這樣想,開始用/5統計的是隻有一個5因子的,但是/25統計的是有兩個5

因子的,由於前面算了一次,現在只需要再加一次即可。依次類推。




2.1~10個箱子,每個箱子裡放1000個球,每個箱子要麼全次品,要麼全正品,每個

正品球質量為100g,每個次品質量為100g.問用天平測一次質量,告訴我哪幾個箱

子裡是次品?


記得以前雄鷹給我看的那個題目是這個題目的縮減版,十個箱子,每個箱子十個球,

每個箱子要麼全次品,要麼全正品,正品質量1kg,次品質量0.9kg.有一個箱子裡是

次品,其他箱子裡都是正品。問用天平測一次質量,告訴我哪個箱子是次品?

這個題目的解法是第一個箱子取1個,第二個箱子取2個。。。。第十個箱子取

10個。這樣根據小數點後面的數字判斷哪個箱子是次品,應該很好懂吧。


還是回到這個題目,開始自己的想法是第一個取1個,第二個取2個,第三個取3個,

第四個取4個。但是這樣卻不合理,因為質量可能出現交叉的情況,9*100=10*90.

所以這樣取球難免有紕漏。我們可以這樣取球,第一箱取1個,第二箱取2個,第三

箱取4個。。。第十箱取512個,這樣很保險,最後可以表示成唯一的1111111111,

相當於每位有了權重,為0則*90,為1則*100。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int a[12];
int b[12];

int main()
{
    int wei;
    cout<<"**************************"<<endl;
    cout<<endl;
    cout<<"**按1:請輸入產品的重量****"<<endl;
    cout<<endl;
    cout<<"**按2:請輸入與全部正的差量****"<<endl;
    cout<<endl;
    cout<<"**按0:退出系統****"<<endl;
    cout<<endl;
    cout<<"**************************"<<endl;

    int ch;
    while(cin>>ch&&ch)
    {
        cin>>wei;
        if(ch==1)
            wei=(10230-wei)/10;
        else wei/=10;

        memset(a,0,sizeof(a));
        int i=1;
        while(wei)
        {
            a[i++]=wei&1;
            wei>>=1;
        }

        int t=0;
        for(i=1;i<=10;i++)
        {
            if(a[i])
                b[t++]=i;
        }
        if(t==0) cout<<"全部為正品"<<endl;
        else
        {
            cout<<"次品為:"<<endl;
            for(i=0;i<t;i++)
                cout<<b[i]<<" ";
            cout<<endl;
        }
    }
    return 0;
}





3.一個人需要到200m的地方去送信,但是他每次行走只能負重120m的糧食。

每走1m需要消耗走1m的糧食。

問這個人最少需要多少糧食才能夠到達送信的地方?


這樣就牽扯到一個問題。怎麼走才能最省糧食,如果能想到這裡,我們就可以先畫

一條線段,AB,A是起點,B是需要到達的地方,AB的長度為200m,我們不妨假設

走1m需要1kg的糧食,如果我們需要消耗最少的糧食,倒著推!我們需要在離A 80m

的C點儲存120kg的糧食即可,等走到C點,就可以一次到達了。每次往B方向走,人

都需要負重120kg,這樣才能達到最省糧食如果要給C運120kg的糧食,不可能一次就

把120kg的糧食直接運到C處。最少需要兩次。我們設還有一個點D,CD=x, D處囤糧

240kg,那麼有2*120-3*x=120,每次往B方向走都帶著120,每次往A走,只需要帶夠

路上吃的就可以了。算出x=40,依次可以找出E點,E處需囤糧360,

設DE=y,360-5*y=240,得到DE=24,現在AE=16,480-7*z=360,z<24,所以可以直接

往E處運糧即可一次負重120運到E處88kg,運三次就有264kg的糧食,最後一次出發只

需要帶上112kg糧食,然後到E處264+112-16剛好等於360.

這樣最少需要帶的糧食為120*3+112.正解為472kg.


今天看了一下暑假做的一些真題,很多方法記得,但是需要用的時候卻想不到,動態

規劃從坐上往右下,雙向看最長能延伸的位置,還有分治的思想,先歸併再列舉,考慮

時間因素。還有就是自己學習的擴充套件KMP題目,很久沒看了,也很模糊。趕緊撿起來,

認真地學習啊,經常溫故才行,而且得學習演算法的真諦。

相關文章