算法筆記入門篇(簡單模擬)

入門篇(1)簡單模擬
3.1 簡單模擬練習

問題 A: 剩下的樹*

有一個長度爲整數L(1<=L<=10000)的馬路,可以想象成數軸上長度爲L的一個線段,起點是座標原點,在每個整數座標點有一棵樹,即在0,1,2,…,L共L+1個位置上有L+1棵樹。
現在要移走一些樹,移走的樹的區間用一對數字表示,如 100 200表示移走從100到200之間(包括端點)所有的樹。
可能有M(1<=M<=100)個區間,區間之間可能有重疊。現在要求移走所有區間的樹之後剩下的樹的個數。

利用數組性質 用每個位置爲 0或1 來表示是否有樹

#include<stdio.h>
int main(){
    int N,M;
    int num[100001]={0};

    while(scanf("%d %d",&N,&M)!=EOF){
        if(N==0&&M==0){
            break;
        }
        if(N>=0 &&N <= 10000){
                //初始化
            for(int i=0;i<=N;i++){
                num[i] = 1;
            }

        }
        if(M>=0 && M<=100){
            int a,b;
            while(M--){

                scanf("%d %d",&a,&b);
                for(int i=a;i<=b;i++){
                    num[i] = 0;
                    //利用數組特性 去掉的位置賦值0
                }
            }

        }
        int c=0;//注意計數變量的位置
        for(int i=0;i<=N;i++){
                if(num[i] ==1){
                    c++;
                }
        }
        printf("%d\n",c);

    }
    return 0;
}

問題 B: A+B
給定兩個整數A和B (-10^9 < A,B < 10^9),其表示形式是:從個位開始,每三位數用逗號","隔開。
樣例輸入:
-234,567,890 123,456,789
1,234 2,345,678
現在請計算A+B的結果,並以正常形式輸出。
問題關鍵:字符串的處理
知識點:字符 轉換到 數字

char a = ‘4’;
int b;
b = a-‘0’;

char自動轉換成int類型,而每個字符都有所代碼的ascii碼值,'0’的ascii碼值是48,而’4’的ascii碼值是52,這樣52-48=4,纔算正常的轉換成整數值。

總結:每一個字符型的數要轉換成整數型都必須減’0’,
因爲char字符型數在計算機中是以ascii碼的形式存在的。

#include<stdio.h>
#include<string.h>

long change(char *x){

    long res=0;
    int len = strlen(x);
    int i=len-1;
    int k = 1;
    while(i>=0){

        if(x[i]>= '0' && x[i]<= '9'){
            res += (x[i]-48) * k;
            k *= 10;//從後往前處理
        }
        i--;
    }
    if(x[0]=='-'){
        res = - res;
    }//注意 第一個字符可能爲負號
    return res;

}
int main(){
    long a1,b1,c;
    char a[12];
    char b[12];
    while(scanf("%s %s",a,b)!=-1){
        a1 = change(a);
        b1 = change(b);
        printf("%ld\n",a1+b1);
    }
    return 0;
}

問題 C: 特殊乘法

寫個算法,對2個小於1000000000的輸入,求結果。
特殊乘法舉例:123 * 45 = 14 +15 +24 +25 +34+35

10^9 以內的整數或32位整數,用int 類型;10^18 以內 或64位整數,用long long 型存放

#include<stdio.h>
int main(){
    int a,b;

    int xa;
    int bb;
    int xc;
    while(scanf("%d %d",&a,&b)!=EOF){
        //範圍判斷
         if (a>1000000000 || b>1000000000)
            continue;
        else{
            //先判斷a是否爲0
            if(a==0){
                printf("0\n");
            }

             xc = 0;//每一次輸入的樣例,總和從0計起
            while (a != 0) {
                //從後往前依次按位相乘
                bb = b;
                while (bb != 0) {
                    xc += (a%10) * (bb%10);
                    bb = bb/10;
                }
                a = a/10;
                if ( a == 0)
                    printf("%d\n",xc);
            }
        }
    }
    return 0;
}

問題 E: Shortest Distance (20)

given N exits on a highway which forms a simple cycle, you are supposed to tell the shortest distance between any pair of exits.
Each input file contains one test case. For each case, the first line contains an integer N (in [3, 105]), followed by N integer distances D1 D2 … DN, where Di is the distance between the i-th and the (i+1)-st exits, and DN is between the N-th and the 1st exits. All the numbers in a line are separated by a space. The second line gives a positive integer M (<=104), with M lines follow, each contains a pair of exit numbers, provided that the exits are numbered from 1 to N. It is guaranteed that the total round trip distance is no more than 10^7.
1.原本思路:從兩個方向上計算路徑和 並比較

#include<stdio.h>
int main(){
    int N;
    int sum;
    int result;
    int sum0=0;
    scanf("%d",&N);
    int d;
    int dist[100000]={0};
    for(int i=1;i<=N;i++){
        scanf("%d",&d);
        dist[i] = d;
        sum0+=d;
    }
    int M;
    scanf("%d",&M);
    int a,b;
    for(int i=0;i<M;i++){
        scanf("%d %d",&a,&b);
        //調整順序使得a<b
        if(a>=b){
            int tmp = a;
            a = b;
            b = tmp;

        }
        sum= 0;
        for(int i=a;i<=b-1;i++){
            sum += dist[i];
            //遍歷數組 從兩個方向上計算路徑和

            if(sum <= sum0 - sum){
                result = sum;
            }
            else{
                result = sum0 - sum;
            }
        }
        printf("%d\n",result);
    }
    return 0;
}

改進:
1.原因分析:
如果不經過對總和 和 路徑和的預處理,那麼每次查詢要遍歷整個數組,大概10的4次方,會導致超時
2.處理方法:
其實總和 和 路徑和的計算累加在讀入數據時即可得到,這樣查詢 left->right ,
dist(left->right) = dis[right] - dist[left] 可以做到查詢的複雜度爲O(1)

#include<stdio.h>
int main(){
    int N;
    int sum;
    int result;
    int sum0=0;
    scanf("%d",&N);
    int d;
    int dist[100000]={0};
    for(int i=1;i<=N;i++){
        scanf("%d",&d);
        dist[i] = sum0;
        //記錄的是截止到目前的總和,例如:1--3的一個方向上的路徑和
        sum0+=d;
    }
    int M;
    scanf("%d",&M);
    int a,b;
    for(int i=0;i<M;i++){
        scanf("%d %d",&a,&b);
        //調整順序使得a<b
        if(a>=b){
            int tmp = a;
            a = b;
            b = tmp;

        }

        sum= 0;
        sum = dist[b] - dist[a];//查詢部分 直接明瞭

            if(sum <= sum0 - sum){
                result = sum;
            }
            else{
                result = sum0 - sum;
            }

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

    }

    return 0;
}

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