算法实战(四)

题目来源(PAT题目)

7-22 龟兔赛跑

题目

乌龟与兔子进行赛跑,跑场是一个矩型跑道,跑道边可以随地进行休息。乌龟每分钟可以前进3米,兔子每分钟前进9米;兔子嫌乌龟跑得慢,觉得肯定能跑赢乌龟,于是,每跑10分钟回头看一下乌龟,若发现自己超过乌龟,就在路边休息,每次休息30分钟,否则继续跑10分钟;而乌龟非常努力,一直跑,不休息。假定乌龟与兔子在同一起点同一时刻开始起跑,请问T分钟后乌龟和兔子谁跑得快?

输入格式:
输入在一行中给出比赛时间T(分钟)。

输出格式:
在一行中输出比赛的结果:乌龟赢输出@@,兔子赢输出_,平局则输出--;后跟1空格,再输出胜利者跑完的距离。

题解

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int main() {
    int i,T, time= 0, sTortoise = 0, sRabbit = 0;
    scanf("%d", &T);
    while (time < T) {  // 退出循环之后也就是time>=T,由于time每次+1,所以退出循环之后,time=T 符合题意
        time++;
        sTortoise += 3; // 跑了1分钟,距离+3
        sRabbit += 9; // 兔子跑了1分钟,距离+9

        if (time % 10 == 0) {
            if (sRabbit - sTortoise > 0) { 
                 // 通过for循环进行控制兔子休息,乌龟跑
                 // 控制条件里面要加上time < T,必须满足这个条件,有可能兔子在休息的时候,乌龟已经到达终点
                for (i = 1; i <= 30 && time < T; i++) {
                    time ++;        // 休息1分钟
                    sTortoise += 3; // 乌龟跑了1分钟,距离+3
                }
            }
            else { // 继续跑10分钟
                for (i = 1; i <= 10 && time < T; i++) {
                    time++;
                    sRabbit += 9;   // 兔子跑了1分钟,距离+9
                    sTortoise += 3; // 乌龟跑了1分钟,距离+3
                }
            }
        }
    }
    // 循环完之后,通过他们两个的距离进行判断谁赢
    if (sRabbit > sTortoise)
        printf("^_^ %d", sRabbit);
    else if (sRabbit < sTortoise)
        printf("@_@ %d", sTortoise);
    else
        printf("-_- %d",sRabbit);
    return 0;
}

7-24 约分最简分式

题目

分数可以表示为分子/分母的形式。编写一个程序,要求用户输入一个分数,然后将其约分为最简分式。最简分式是指分子和分母不具有可以约分的成分了。如6/12可以被约分为1/2。当分子大于分母时,不需要表达为整数又分数的形式,即11/8还是11/8;而当分子分母相等时,仍然表达为1/1的分数形式。

输入格式:
输入在一行中给出一个分数,分子和分母中间以斜杠/分隔,如:12/34表示34分之12。分子和分母都是正整数(不包含0,如果不清楚正整数的定义的话)。

提示:

对于C语言,在scanf的格式字符串中加入/,让scanf来处理这个斜杠。
对于Python语言,用a,b=map(int, input().split(‘/’))这样的代码来处理这个斜杠。
输出格式:
在一行中输出这个分数对应的最简分式,格式与输入的相同,即采用分子/分母的形式表示分数。如
5/6表示6分之5。

题解

#include<stdio.h>

// 寻找最大公约数
int gcd(int a,int b){
    if(b == 0)
        return a;
    return gcd(b,a%b);
}

int main(){
    int numerator,denominator,common; // 分子 分母
    scanf("%d/%d",&numerator,&denominator);
    common=gcd(numerator,denominator);
    if(common!=1){ // 有最大公约数
        numerator/=common;
        denominator/=common;
    }else if(numerator==denominator){
        numerator=denominator=1;
    }
    printf("%d/%d",numerator,denominator);
    return 0;
}

求最大公约数方法三种方法

7-25 念数字

题目

输入一个整数,输出每个数字对应的拼音。当整数为负数时,先输出fu字。十个数字对应的拼音如下:

0: ling
1: yi
2: er
3: san
4: si
5: wu
6: liu
7: qi
8: ba
9: jiu
输入格式:
输入在一行中给出一个整数,如:1234。

提示:整数包括负数、零和正数。

输出格式:
在一行中输出这个整数对应的拼音,每个数字的拼音之间用空格分开,行末没有最后的空格。如
yi er san si。

原理

通过scanf获得数字之后,如果是0的话,通过0在maps集合里面进行索引,结束程序即可;如果为负数的话,如果是取为相反数,并且把标志位设为true; 然后把每一位逆序保存在数组当中去,然后如果flag为true, 说明就是负数,所以要打印出来“fu”,然后的话,通过从后往前遍历数组,然后在maps集合进行索引,输出字符即可。

题解

#define _CRT_SECURE_NO_WARNINGS
#include<map>
#include<stdio.h>
#include<string>
#include <iostream>
using namespace std;

void initializeMap(std::map<int, std::string>& maps) {
    maps = {
        {0, "ling"},{1, "yi"},{2, "er"},{3, "san"},{4, "si"},{5, "wu"},{6, "liu"},{7, "qi"},{8, "ba"},{9, "jiu"} };
}

int main() {
    map<int,string> maps;
    initializeMap(maps);
    int number, count = 0, array[10] = { 0 };
    bool flag=false;   // 通过flag位来标志是不是负数
    scanf("%d", &number);
    if (number == 0) { // 为0
        cout << maps[number];
        return 0;
    }
    else {
        if (number < 0) {
            flag = true;
            number = -number;
        }
        while (number) {  // 把数字的每一位保存在数组中
            array[count++] = number % 10;
            number /= 10;
        }
        if (flag == true)
            printf("fu ");
        
        for (int i = count - 1; i >= 0; i--) { // 从后往前遍历数组,然后通过数组里面存放的值在maps集合里面进行索引,把结果打印出来。
            if (i == count - 1)
                cout << maps[array[i]];
            else
                cout << " " << maps[array[i]];
        }
    }
    return 0;
}

7-27 冒泡法排序

题目

将N个整数按从小到大排序的冒泡排序法是这样工作的:从头到尾比较相邻两个元素,如果前面的元素大于其紧随的后面元素,则交换它们。通过一遍扫描,则最后一个元素必定是最大的元素。然后用同样的方法对前N−1个元素进行第二遍扫描。依此类推,最后只需处理两个元素,就完成了对N个数的排序。

本题要求对任意给定的K(<N),输出扫描完第K遍后的中间结果数列。

输入格式:
输入在第1行中给出N和K(1≤K<N≤100),在第2行中给出N个待排序的整数,数字间以空格分隔。

输出格式:
在一行中输出冒泡排序法扫描完第K遍后的中间结果数列,数字间以空格分隔,但末尾不得有多余空格。

题解

#include <iostream>
using namespace std;
void BubblrSort(int arr[], int N, int K);
void Print(int arr[],int N);

int main()
{
    int N, K;
    cin >> N >> K;
    int arr[100];
    for (int i = 0; i < N; i++)
        cin >> arr[i];
    BubblrSort(arr, N, K); // 进行冒泡排序
    Print(arr,N);          // 打印第K躺的结果
    return 0;
}

void BubblrSort(int arr[], int N, int K)
{
    for (int i = 1; i < N && i<=K; ++i)
    {
        for (int j = 0; j < N - i; ++j)
            if (arr[j] > arr[j + 1])
                swap(arr[j], arr[j + 1]);
    }
}

void Print(int arr[],int N){
    for (int i = 0; i < N; i++){
        if (i != N - 1)     // 如果是最后一个的话不会打印多余空格
            cout << arr[i] << " ";
        else
            cout << arr[i];
    }  
}

7-33 有理数加法

题目

本题要求编写程序,计算两个有理数的和。

输入格式:
输入在一行中按照a1/b1 a2/b2的格式给出两个分数形式的有理数,其中分子和分母全是整形范围内的正整数。

输出格式:
在一行中按照a/b的格式输出两个有理数的和。注意必须是该有理数的最简分数形式,若分母为1,则只输出分子。

题解

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int gcd(int a,int b);
int lcm(int a,int b);

int main() {
    int temp,numerator1, denominator1, numerator2, denominator2,common,common1;
    scanf("%d/%d %d/%d", &numerator1, &denominator1, &numerator2, &denominator2);

    if (denominator1 != denominator2) { // 分母如果不相同,说明需要求最大公倍数
        common = lcm(denominator1, denominator2); // 求的最大公倍数
        if (common == denominator2) { // 进行通分
            temp = common / denominator1;
            numerator1 *= temp;
            denominator1 *= temp;
        }
        else if(common==denominator1){
            temp = common / denominator2;
            numerator2 *= temp;
            denominator2 *= temp;
        }
        else {
            temp = common / denominator1;
            numerator1 *= temp;
            denominator1 *= temp;
            temp = common / denominator2;
            numerator2 *= temp;
            denominator2 *= temp;
        }
        // 继续约分
        common1 = gcd(numerator1 + numerator2, common);
        if (common != 1) { // 进行约分
            if (common / common1 == 1)
                printf("%d", (numerator1+numerator2) / common1);
            else 
                printf("%d/%d", (numerator1+numerator2) / common1, common / common1);
        }
        
    }
    else { // 分母相同,不需要约分
        common = gcd(numerator1 + numerator2, denominator1);
        if (common != 1) {   // 需要约分
            if ((numerator1 + numerator2) / denominator1)
                printf("%d", (numerator1 + numerator2) / denominator1);
            else
                printf("%d/%d", (numerator1 + numerator2) / common, denominator1 / common);
        }
        
    }

    return 0;
}

// 求的最大公约数
int gcd(int a, int b) {
    if (b == 0)
        return a;
    return gcd(b, a % b);
}

// 最小公倍数
int lcm(int a, int b) {
    return (a * b) / gcd(a, b);
}

总结

该题目最重要的就是最大公约数、最小公倍数两个函数

下一篇

链接: 算法实战(五)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CPanMirai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值