算法题集(一)

这几天刚入门算法一直在刷PAT习题,emmmmm….主要是想记录一下自己做题的思路,还有因为我(菜鸟)在做这些题的时候,有时候会觉得自己的代码还不够好或者不会,想在网上搜搜大神们的代码时…..遇到了瓶颈…….大神们的代码,几乎全用的是C++……而我…..不怎么能看的懂,虽然比起C++用C做题会显得巨艰难,但是我始终相信思维是最重要的!!!先挑L1里几道我觉得比较巧妙的题写一写(先暂时写个大概思路,以后再细细剖析)

1.帅到没朋友

当芸芸众生忙着在朋友圈中发照片的时候,总有一些人因为太帅而没有朋友。本题就要求你找出那些帅到没有朋友的人。
输入格式:
输入第一行给出一个正整数N(<=100),是已知朋友圈的个数;随后N行,每行首先给出一个正整数K(<=1000),为朋友圈中的人数,然后列出一个朋友圈内的所有人——为方便起见,每人对应一个ID号,为5位数字(从00000到99999),ID间以空格分隔;之后给出一个正整数M(<=10000),为待查询的人数;随后一行中列出M个待查询的ID,以空格分隔。
注意:没有朋友的人可以是根本没安装“朋友圈”,也可以是只有自己一个人在朋友圈的人。虽然有个别自恋狂会自己把自己反复加进朋友圈,但题目保证所有K超过1的朋友圈里都至少有2个不同的人。
输出格式:
按输入的顺序输出那些帅到没朋友的人。ID间用1个空格分隔,行的首尾不得有多余空格。如果没有人太帅,则输出“No one is handsome”。
注意:同一个人可以被查询多次,但只输出一次。
输入样例1:
3
3 11111 22222 55555
2 33333 44444
4 55555 66666 99999 77777
8
55555 44444 10000 88888 22222 11111 23333 88888
输出样例1:
10000 88888 23333
输入样例2:
3
3 11111 22222 55555
2 33333 44444
4 55555 66666 99999 77777
4
55555 44444 22222 11111
输出样例2:
No one is handsome

#include<stdio.h>
int main()
{
    int peo[100000] = { 0 };
    int i = 0;
    int j = 0;
    int N = 0;
    int n = 0;
    int m = 0;
    int k = 0;
    int sum = 0;
    scanf("%d", &N);
    for (i = 0; i < N; i++)
    {
        scanf("%d", &n);
        for (j = 0; j < n; j++)
        {
            scanf("%d", &m);
            if (n != 1)
            {
                peo[m] += 1;
            }
        }
    }
    scanf("%d", &k);
    for (i = 0; i < k; i++)
    {
        scanf("%d", &m);
        if (peo[m] == 0)
        {
            if (sum)
            {
                printf(" ");
            }
            printf("%05d ", m);
            peo[m] = -1;
            sum++;
        }

    }
    if (sum == 0)
    {
        printf("No one is handsome\n");
    }
    system("pause");
    return 0;
}

2. 古风排版

中国的古人写文字,是从右向左竖向排版的。本题就请你编写程序,把一段文字按古风排版。
输入格式:
输入在第一行给出一个正整数N(<100),是每一列的字符数。第二行给出一个长度不超过1000的非空字符串,以回车结束。
输出格式:
按古风格式排版给定的字符串,每列N个字符(除了最后一列可能不足N个)
输入样例:
4
This is a test case
输出样例:
asa T
st ih
e tsi
ce s

#include<stdlib.h>
#include<string.h>
int main()
{
    char str[1001] = { 0 };
    char ch[10001][100] = { 0};
    int n = 0;
    int i = 0; 
    int j = 0;
    int len = 0;
    int k = 0;
    int col = 0;
    scanf("%d", &n);
    getchar();
    gets(str);
    len = strlen(str);
    col = len / n;
    for (i = 0; i < n; i++)
    {
        ch[i][0] = ' ';
    }
    if ((len%n) == 0)
    {
        col = col - 1;
    }
    for (i = col; i >= 0; i--)
    {
        for (j = 0; j <n; j++)
        {
            ch[j][i] = str[k++];

        }
        if (k == len)
        {
            break;
        }
    }
    for (i = 0; i < n; i++)
    {
        for (j = 0; j <= col; j++)
        {
            putchar(ch[i][j]);
        }
        printf("\n");
    }
    system("pause");
    return 0;
}

3.谁先到

划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和,谁就输了,输家罚一杯酒。两人同赢或两人同输则继续下一轮,直到唯一的赢家出现。
下面给出甲、乙两人的酒量(最多能喝多少杯不倒)和划拳记录,请你判断两个人谁先倒。
输入格式:
输入第一行先后给出甲、乙两人的酒量(不超过100的非负整数),以空格分隔。下一行给出一个正整数N(<=100),随后N行,每行给出一轮划拳的记录,格式为:
甲喊 甲划 乙喊 乙划
其中“喊”是喊出的数字,“划”是划出的数字,均为不超过100的正整数(两只手一起划)。
输出格式:
在第一行中输出先倒下的那个人:A代表甲,B代表乙。第二行中输出没倒的那个人喝了多少杯。题目保证有一个人倒下。注意程序处理到有人倒下就终止,后面的数据不必处理。
输入样例:
1 1
6
8 10 9 12
5 10 5 10
3 8 5 12
12 18 1 13
4 16 12 15
15 1 1 16
输出样例:
A
1

谁先到
int main()
{

        int N=0; 
        int A_lose = 0, B_lose = 0;
        int A_he = 0, B_he = 0;
        int a1, a2, a3, a4;
        int i = 0; 
        int tag1 = 0;
        int tag2 = 0;
        scanf("%d %d", &A_he, &B_he);
        scanf("%d", &N);
        for (i = 0; i < N; i++)
        {
            scanf("%d%d%d%d", &a1, &a2, &a3, &a4);
            if (a2 == (a1 + a3))
            {
                tag1++;
            }
            else
            {
                tag1 = 0;
            }
            if (a4 == (a1 + a3))
            {
                tag2++;
            }
            else
            {
                tag2 = 0;
            }
            if (tag1 != tag2)
            {
                if (tag1)
                {
                    A_lose++;
                    if (A_lose > A_he)
                    {
                        printf("A\n%d\n", B_lose);
                        break;
                    }
                }
                else
                {
                    B_lose++;
                    if (B_lose > B_he)
                    {
                        printf("B\n%d\n", A_lose);
                        break;
                    }
                }

            }
        }

    system("pause");
    return 0;
}

4.正整数A+B

本题的目标很简单,就是求两个正整数A和B的和,其中A和B都在区间[1,1000]。稍微有点麻烦的是,输入并不保证是两个正整数。
输入格式:
输入在一行给出A和B,其间以空格分开。问题是A和B不一定是满足要求的正整数,有时候可能是超出范围的数字、负数、带小数点的实数、甚至是一堆乱码。
注意:我们把输入中出现的第1个空格认为是A和B的分隔。题目保证至少存在一个空格,并且B不是一个空字符串。
输出格式:
如果输入的确是两个正整数,则按格式“A + B = 和”输出。如果某个输入不合要求,则在相应位置输出“?”,显然此时和也是“?”。
输入样例1:
123 456
输出样例1:
123 + 456 = 579
输入样例2:
22. 18
输出样例2:
? + 18 = ?
输入样例3:
-100 blabla bla…33
输出样例3:
? + ? = ?

#include <stdlib.h>  
int check(char p[])
{
    int i = 1;
    if (!(p[0] >= '0' && p[0] <= '9' || p[0] == '+'))
        return 0;
    while (p[i] != 0)
    {
        if (!(p[i] >= '0' && p[i] <= '9'))
            return 0;
        i++;
    }
    return 1;
}

int main()
{
    char a[6], b[6];
    int flagA, flagB, A, B, i;
    for (i = 0; i<5; i++)
    {
        a[i] = getchar();
        if (a[i] == ' ')
        {
            break;
        }
    }
    a[i] = 0;
    for (i = 0; i<5; i++)
    {
        b[i] = getchar();
        if (b[i] == '\n')
        {
            break;
        }
    }
    b[i] = 0;
    flagA = check(a);
    flagB = check(b);
    if (flagA)
    {
        A = atoi(a);
        flagA = (A >= 1 && A <= 1000);
    }
    if (flagB)
    {
        B = atoi(b);
        flagB = (B >= 1 && B <= 1000);
    }
    if (flagA && flagB)
    {
        printf("%d + %d = %d\n", A, B, A + B);
    }
    if (flagA == 1 && flagB == 0)
    {
        printf("%d + ? = ?\n", A);
    }
    if (flagA == 0 && flagB == 1)
    {
        printf("? + %d = ?\n", B);
    }
    if (flagA == 0 && flagB == 0)
    {
        printf("? + ? = ?\n");
    }
    system("pause");
    return 0;
}

5.连续因子

一个正整数N的因子中可能存在若干连续的数字。例如630可以分解为3*5*6*7,其中5、6、7就是3个连续的数字。给定任一正整数N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。
输入格式:
输入在一行中给出一个正整数N(1

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
int main()
{
    int N = 0, i = 0, sq = 0;
    while (scanf("%d", &N) != EOF)
    {
        char a[1010] = { 0 }, temp[1010] = { 0 };
        int n = 0;
        sq = (int)sqrt(N) + 1;
        for (i = 2; i <= sq; i++)
        {
            int count = 0;
            int j = 0;
            if (N%i == 0)
            {
                int t = N / i;
                temp[count++] = i;
                for (j = i + 1; j <= sq; j++)
                {
                    if (t%j == 0)
                    {
                        temp[count++] = j;
                        t /= j;
                    }
                    else
                        break;
                }
                if (count > n){ strcpy(a, temp); n = count; }
            }
        }
        if (n == 0) printf("%d\n%d", 1, N);
        else
        {
            printf("%d\n", n);
            for (i = 0; i < n; i++)
            {
                if (i == 0)
                    printf("%d", a[i]);
                else {
                    printf("*%d", a[i]);
                }
            }
        }
        printf("\n");

    }
    system("pause");
    return 0;
}

6.打印漏斗

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印



*



所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式:
输入在一行给出1个正整数N(<=1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例:
19 *
输出样例:



*



2


#include<stdio.h>
int main()
{
    int n = 0;
    int num = 0;
    int sum = 0;
    int i = 0;
    int k = 0;
    int j = 0;
    char str = 0;
    while (scanf("%d %c", &n, &str) != EOF)
    {
        sum = -1;
        num = 0;
        while (n >= sum)
        {
            num++;
            sum += 2 * (2 * num - 1);
        }
        num = num - 1;

        for (k = 0; k < num; k++)
        {
            for (j = 0; j <k; j++)
            {
                printf(" ");
            }
            for (i = 2 * num - 1; i > 2 * k; i--)
            {
                printf("%c", str);
            }
            printf("\n");
        }
        for (k = 1; k < num; k++)
        {
            for (j = num-1; j >k; j--)
            {
                printf(" ");
            }
            for (i = 0; i < 2 * k + 1; i++)
            {
                printf("%c", str);
            }
            printf("\n");
        }

        sum = 0;
        for (i = 1; i <= num; i++)
        {
            sum += 2 * (2 * i - 1);
        }
        printf("%d\n", n - sum + 1);
    }
    system("pause");
    return 0;
}

7.月饼

月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。
注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有3种月饼,其库存量分别为18、15、10万吨,总售价分别为75、72、45亿元。如果市场的最大需求量只有20万吨,那么我们最大收益策略应该是卖出全部15万吨第2种月饼、以及5万吨第3种月饼,获得 72 + 45/2 = 94.5(亿元)。
输入格式:
每个输入包含1个测试用例。每个测试用例先给出一个不超过1000的正整数N表示月饼的种类数、以及不超过500(以万吨为单位)的正整数D表示市场最大需求量。随后一行给出N个正数表示每种月饼的库存量(以万吨为单位);最后一行给出N个正数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。
输出格式:
对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后2位。
输入样例:
3 20
18 15 10
75 72 45
输出样例:
94.50

#include<stdio.h>
int Max(double c[],int n)
{
    int i = 0;
    int max = 0;
    for (i = 1; i < n; i++)
    {
        if (c[max] < c[i])
        {
            max = i;
        }
    }
    return max;
}
int main()
{
    int N = 0;
    int D = 0;
    int i = 0, max = 0;
    double sum = 0;
    double c[1000] = { 0 }, a[1000] = { 0 }, b[1000] = { 0 };
    scanf("%d%d", &N,&D);
    for (i = 0; i < N; i++)
    {
        scanf("%lf", &a[i]);
    }
    for (i = 0; i < N; i++)
    {
        scanf("%lf", &b[i]);
        c[i] = b[i] / a[i];
    }

    while (D>0)
    {
        if (a[Max(c, N)] >= D)
        {
            sum += (b[Max(c, N)] / a[Max(c, N)]) * D;
            printf("%.2f\n", sum);
            break;
        }
        else
        {
            sum += b[Max(c, N)];
            D = D -(int) a[Max(c, N)];
            c[Max(c, N)] = 0;

        }
    }
    system("pause");
    return 0;
}

8.整除光棍

这里所谓的“光棍”,并不是指单身汪啦~ 说的是全部由1组成的数字,比如1、11、111、1111等。传说任何一个光棍都能被一个不以5结尾的奇数整除。比如,111111就可以被13整除。 现在,你的程序要读入一个整数x,这个整数一定是奇数并且不以5结尾。然后,经过计算,输出两个数字:第一个数字s,表示x乘以s是一个光棍,第二个数字n是这个光棍的位数。这样的解当然不是唯一的,题目要求你输出最小的解。
提示:一个显然的办法是逐渐增加光棍的位数,直到可以整除x为止。但难点在于,s可能是个非常大的数 —— 比如,程序输入31,那么就输出3584229390681和15,因为31乘以3584229390681的结果是111111111111111,一共15个1。
输入格式:
输入在一行中给出一个不以5结尾的正奇数x(< 1000)。
输出格式:
在一行中输出相应的最小的s和n,其间以1个空格分隔。
输入样例:
31
输出样例:
3584229390681 15

#include<stdio.h>
int main()
{
    int n;
    char str[1001];

    int p = 0;
    int now = 1;
    int len = 0;
    scanf("%d", &n);
    while (1) {
        if (p || now / n) {
            str[p++] = '0' + now / n;
        }
        len++;
        now %= n;
        if (now == 0)
        {
            str[p] = 0;
            printf("%s %d", str, len);

            break;
        }
        now = now * 10 + 1;
    }
    system("pause");
    return 0;
}

献给同暂时抗拒c++的同道中人…….

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值