算法笔记入门篇(简单模拟)

入门篇(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;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值