CS50--Week1--Cash和Credit

week1的第三题

1.找零(贪心算法)

在进行找零时,希望尽量减少为每位顾客分配的硬币数量。假设收银员欠客户一些零钱,收银员的抽屉里有 25 美分、10 美分、5 美分硬币和1 美分硬币,要解决的问题是怎样选择硬币及数量才能使找零的硬币数量最少。比如需要找零41美分,按照贪心算法,需要找以上四种硬币各1个才能保证数额正确且硬币数最少。这个尽快找大面额硬币就能保证找的硬币数最少,具体如下:

#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void)
{
    int c25=25,c10=10,c5=5,c1=1;//定义四种硬币
    float change=get_float("The change is($):\n");//输入找零钱数,单位为美元 
    while(change<=0)//找零小于等于0时重新输入
    {
        change=get_float("The change is($):\n");
    }

    int changes=ceil(change*100);//美元转化为美分

    int n1,n2,n3,n4;//定义每种找零的硬币数量


    n1=changes/c25;
    n2=(changes%c25)/c10;
    n3=((changes%c25)%c10)/c5;
    n4=(((changes%c25)%c10)%c5)/c1;
    printf("The number of total coins is %i\n",n1+n2+n3+n4); //总数量         
    printf("25,10,5,1:  %i,%i,%i,%i\n",n1,n2,n3,n4);//各自数量
}

其中包含math头文件是采用ceil函数进行float和int的转化。

结果如下

 

 

 

2. 信用卡

信用卡或借记卡的卡号是需要进行验证来确定卡的真假的,验证方法一般为Luhn算法,具体描述如下:

1.从卡号的倒数第二个数字开始,每隔一个数字乘以 2,然后将每一位得出的商按个位上的数字加十位上的数字全部相加(只有一位的话按照十位为0相加)。

2.将第一步的总和与未乘以 2 的位数上的的总和相加。

3.如果总数的最后一位数字是 0,则该卡号是有效的!

算法不复杂,就是操作繁琐,卡号用的longlong,先求取卡号的总位数,再把卡号每位数字都求出来,同时把要×2的和不×2的分开,要×2的乘2后再拆分成个位和十位相加,不乘2的直接相加,把俩结果相加对10求余即可判断个位是否为0.具体程序如下:

#include <stdio.h>
#include <math.h>

int main()
{
    long long card,card1;//长长整形;长整形不能记录13甚至15位的整数;
    int sum = 0,sum1=0;//sum记录未×2的那些位的和;sum1记录×2后再拆分相加的和;
    scanf_s("%lld", &card);
    card1 = card;       //将卡号赋值给card和card1;
    int i;
    for (i = 0; card != 0; i++)//求取卡号总位数
    {
        card /= 10;
    }
    int digit = i;//记录卡总位数

    int arr[20];//存储卡号每位的值;
    int arr1[20];//存储要×2的那些位;

    for (int j = 0; j < digit; j++)
    {
        
        arr[j] = card1 % 10;
        card1 /= 10;
        
        if (j % 2 != 0)//判断是否是要x2的位
        {
            arr1[(j-1)/2]=arr[j]*2;//存储要×2的那些位;
        }
        else
            sum += arr[j];//不需要*2的那些位先加起来;
    }

    //判断需要*2的那些位的位数;
    int count = 0;
    if (digit % 2 != 0)
        count = (digit - 1) / 2;
    else
        count = ceil(digit/2);

    //arr1中每个数拆成十位和个位,就算是一位也拆成十位和个位,直接相加;
    for (int k = 0; k < count; k++)
    {
        sum1 += arr1[k] % 10;
        arr1[k] /= 10;
        sum1 += arr1[k] % 10;
    }

    if ((sum+sum1) % 10 == 0)
        printf("the card is legit!\n");
    else
        printf("the card is illegit!\n");



}

运行结果:

输入合法卡号4003600000000014显示legit。

输入非法卡号4003600000000016显示illegit。

 

 

题目来源:https://docs.cs50.net/2019/x/psets/1/index.html

posted @ 2022-04-27 21:01  soranonioi  阅读(381)  评论(0编辑  收藏  举报