算法竞赛入门经典 第三章部分题解

目录

 

1、程序3-3 蛇形填数

2、程序3-7 回文词

3、例题3-6 环状序列

4、习题3-2 分子量(Molar Mass, ACM/ICPC Seoul 2007, UVa1586)

5、习题3-4 周期串

6、习题3-5 谜题(Puzzle, ACM/ICPC World Finals 1993, UVa227)


 

1、程序3-3 蛇形填数

 

在n×n方阵里填入1,2,…,n×n,要求填成蛇形。例如,n=4时方阵为:
10  11  12  1
9    16  13  2
8    15  14  3
7     6   5    4

思路:
找到程序的起点和终点,发现起点为矩阵右上角,需要控制行终点和列终点,分为四次循环分别打印,从上往下、从右往左、从下往上、从左往右,直到循环次数到n*n。

#include 
#include 

int arr[100][100] = {0};

int main ()
{
    int n;
    while(scanf("%d", &n)!= EOF)
    {
        memset(arr, 0, sizeof(arr));
        int i = 0, j = n-1, sum = 1;
        arr[i][j]=1;
        while(sum < n*n)
        {
            while(i+1=0 && !arr[i][j-1])   arr[i][--j] = ++sum;
            while(i-1>=0 && !arr[i-1][j])   arr[--i][j] = ++sum;
            while(j+1

 

看大神博客发现类似的题目记录下:

原帖链接:https://blog.csdn.net/qq_36238595/article/details/53537672

斜着打印

1  3  6  10

2  5  9

4  8

输入层数n,打印类似图案。

#include 

int a[10][10]= {0};

int main()
{
    int n, i = 1, j, x = 1, y = 0, c = 1;
    a[0][0] = 1;
    scanf("%d",&n);
    while (i

 

 

2、程序3-7 回文词

输入一个字符串,判断它是否为回文串以及镜像串。输入字符串保证不含数字0。所谓回文串,就是反转以后和原串相同,如abba和madam。所有镜像串,就是左右镜像之后和原串相同,如2S和3AIAE。注意,并不是每个字符在镜像之后都能得到一个合法字符。在本题中,每个字符的镜像如图所示(空白项表示该字符镜像后不能得到一个合法字符)。

算法竞赛入门经典 第三章部分题解_第1张图片

输入的每行包含一个字符串(保证只有上述字符。不含空白字符),判断它是否为回文串和镜像串(共4种组合)。每组数据之后输出一个空行。


样例输入:
NOTAPALINDROME
ISAPALINILAPASI
2A3MEAS
ATOYOTA


样例输出:
NOTAPALINDROME -- is not a palindrome.
ISAPALINILAPASI -- is a regular palindrome.
2A3MEAS -- is a mirrored string.
ATOYOTA -- is a mirrored palindrome.

分析:

回文串比较好判断,前后比较就行了,镜像串需要先看有没有镜像文字,然后比较。

书中用数组存储镜像文字比较简单。

#include
#include
#include
const char* rev = "A 3 HIL JM O 2TUVWXY51SE Z 8 ";
const char* msg[] = {"not a palindrome", "a regular palindrome", "a mirrored string", "a mirrored palindrome"};
char r(char ch)
{
    if(isalpha(ch))
        return rev[ch - 'A'];
    return rev[ch - '0' + 25];
}
int main()
{
    char s[30];
    while(scanf("%s", s) == 1)
    {
        int len = strlen(s);
        int p = 1, m = 1;
        for(int i = 0; i < (len+1)/2; i++)
        {
            if(s[i] != s[len-1-i])
                p = 0; //不是回文串
            if(r(s[i]) != s[len-1-i])
                m = 0; //不是镜像串
        }
        printf("%s -- is %s.\n\n", s, msg[m*2+p]);
    }
    return 0;
}

 

 

3、例题3-6 环状序列

 

长度为n的环状串有n种表示法,分别为从某个位置开始顺时针得到。如图的环状串

算法竞赛入门经典 第三章部分题解_第2张图片


有10种表示:
CGAGTCAGCT,GAGTCAGCTC,AGTCAGCTCG等。在这些表示法中,字典序最小的称
为"最小表示"。
输入一个长度为n(n≤100)的环状DNA串(只包含A、C、G、T这4种字符)的一种表
示法,你的任务是输出该环状串的最小表示。例如,CTCC的最小表示是
CCCT,CGAGTCAGCT的最小表示为AGCTCGAGTC。

 

 

思路:

注意理解环状串,字母不能变更顺序,用strcmp需要自己构造每一个串让头尾相接,比较麻烦

 

#include
#include

int main ()
{
    char arr[105] = {};
    scanf("%s",arr);
    int n = strlen(arr);
    int ans = 0;
    for(int i = 1; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            if(arr[(i+j)%n] != arr[(j+ans)%n])
            {
                if(arr[(i+j)%n] < arr[(ans+j)%n])
                    ans = i;
                break;

            }
        }

    }

    for(int i = 0; i < n; i++)
        putchar(arr[(ans+i)%n]);
    putchar('\n');

    return 0;
}

 

 

 

 

 

 

4、习题3-2 分子量(Molar Mass, ACM/ICPC Seoul 2007, UVa1586)

 

When an organic compound is given as a molecular for-
mula, Dr. CHON wants to find its molar mass. A molecular
formula, such as C 3 H 4 O 3 , identifies each constituent element by
its chemical symbol and indicates the number of atoms of each
element found in each discrete molecule of that compound. If
a molecule contains more than one atom of a particular ele-
ment, this quantity is indicated using a subscript after the chemical symbol.
In this problem, we assume that the molecular formula is represented by only four elements, ‘C’
(Carbon), ‘H’ (Hydrogen), ‘O’ (Oxygen), and ‘N’ (Nitrogen) without parentheses.
The following table shows that the standard atomic weights for ‘C’, ‘H’, ‘O’, and ‘N’.
Atomic Name Carbon Hydrogen Oxygen Nitrogen
Standard Atomic Weight 12.01 g/mol 1.008 g/mol 16.00 g/mol 14.01 g/mol
For example, the molar mass of a molecular formula C 6 H 5 OH is 94.108 g/mol which is computed by
6 × (12.01 g/mol) + 6 × (1.008 g/mol) + 1 × (16.00 g/mol).
Given a molecular formula, write a program to compute the molar mass of the formula.


Input
Your program is to read from standard input. The input consists of T test cases. The number of test
cases T is given in the first line of the input. Each test case is given in a single line, which contains
a molecular formula as a string. The chemical symbol is given by a capital letter and the length of
the string is greater than 0 and less than 80. The quantity number n which is represented after the
chemical symbol would be omitted when the number is 1 (2 ≤ n ≤ 99).


Output
Your program is to write to standard output. Print exactly one line for each test case. The line should
contain the molar mass of the given molecular formula.


Sample Input
4
C
C6H5OH
NH2CH2COOH
C12H22O11


Sample Output
12.010
94.108
75.070
342.296

 

 

开始想很复杂,考虑精度问题、原子个数的位数,结果写条件判断时候以为isalnum()的功能是判断是否为数字,没有查帮助文档,结果卡了快一个小时,写一堆打印中间结果的还是找不出问题在哪里,晕……

经验不足啊,继续加油吧

 

#include
#include
#include
int main ()
{
    int T;
    scanf("%d", &T);
    const double c = 12.01, h = 1.008, o = 16.00, n = 14.01;
    while(T--)
    {
        char s[100] = {0};
        scanf("%s", s);
        int len = strlen(s);
        int arr[30] = {0};
        int cnt = 0, tmp = 0;
        for(int i = 0; i < len;)
        {
            if( isalpha(s[i]))
            {
                if(isalpha(s[i+1]) || s[i+1] == '\0')
                {
                    ++arr[s[i]-'A'];
                }
                else if(isdigit(s[i+1]))
                {
                    tmp = i;
                }
				i++;
                continue;
            }
            if(isdigit(s[i]))
            {
                while(isdigit(s[i]))
                {
                    cnt = cnt*10 + (s[i]-'0');
                    i++;
                }
            }

            arr[s[tmp]-'A'] += cnt;
//            printf("arr[%c] = %d\t\ttmp = %d\t\tcnt = %d\n", s[tmp],arr[s[tmp]-'0'], tmp, cnt);
//            printf("N = %d\tH = %d\tO = %d\tC = %d\n", arr['N'-'A'], arr['H'-'A'], arr['O'-'A'], arr['C'-'A']);
            cnt = 0;
        }
        double ans = arr['N'-'A']*n + arr['H'-'A']*h +  arr['O'-'A']*o+ arr['C'-'A'] * c;
        printf("%.3lf\n", ans);
    }


    return 0;
}
/*
4
C
C6H5OH
NH2CH2COOH
C12H22O11
*/

PS:觉得UVa慢的到Virtual Judge上面做题目,访问快很多。

 

 

 

 

5、习题3-4 周期串

A character stringis said to have periodk if it can be formed by concatenating one or morerepetitions of anotherstring of lengthk. For example, the string”abcabcabcabc” has period 3, since it is formed by 4 repetitionsof the string ”abc”. Italso has periods 6 (tworepetitions of ”abcabc”) and 12 (one repetition of ”abcabcabcabc”).

Write a program to read a character stringand determine its smallest period.

 

Input
The first lineoif the inputfile will contain a single integer N indicating how many test casethat your program will test followed by a blank line. Each test case will containa single characterstring of up to 80 non-blank characters.Two consecutive input will separated by a blankline.

 

Output
An integerdenoting the smallest period of the inputstring for each input.Two consecutive output are separated by a blank line.

 

Sample Input
1

HoHoHo

 

Sample Output
2

 

开始时候判断条件就写错,没多想以为就是求因数,判断到sqrt就够了,结果一直WA,{由于小因数可以推出它倍数的周期是充分不必要条件,比如2个为循环的在数据足够长时候4个为一个周期也行,但是4个为一个周期不能推出2个也能为一个周期的结论,一直忽略了这一点},卡了很长时间,后来又卡在格式上,改了几次才好。

 

 

#include
#include
#include
#include 
#include 


int main ()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        char s[100];
        scanf("%s", s);
        int len = strlen(s);
        int a = sqrt(len);
        int ans = len;
        for(int i = 1; i <= len; i++)
        {
            if(len%i == 0)
            {
                int j = i;
                for(; j < len; j++)
                {
                    if(s[j] != s[j%i])
                        break;
                }
                if(j == len)
                {
                    ans = i;
                    break;
                }
            }
        }
        printf("%d\n", ans);
        if(T)printf("\n");
    }





    return 0;
}
/*
4
HoHoHo
HWE
WEEWEEWEEWEE
ABCDABCDABCD

*/

 

           

6、习题3-5 谜题(Puzzle, ACM/ICPC World Finals 1993, UVa227)

有一个5*5的网格,其中恰好有一个格子是空的,其他格子各有一个字母。一共有4种指
令:A, B, L, R,分别表示把空格上、下、左、右的相邻字母移到空格中。输入初始网格和指
令序列(以数字0结束),输出指令执行完毕后的网格。如果有非法指令,应输出“This
puzzle has no final configuration.”,例如,图3-5中执行ARRBBL0后,

算法竞赛入门经典 第三章部分题解_第3张图片算法竞赛入门经典 第三章部分题解_第4张图片

 

Sample Input


TRGSJ
XDOKI
M VLN
WPABE
UQHCF
ARRBBL0
ABCDE
FGHIJ
KLMNO
PQRS
TUVWX
AAA
LLLL0
ABCDE
FGHIJ
KLMNO
PQRS
TUVWX
AAAAABBRRRLL0
Z


Sample Output


Puzzle #1:
T R G S J
X O K L I
M D V B N
W P A E
U Q H C F
Puzzle #2:
A B C D
F G H I E
K L M N J
P Q R S O
T U V W X
Puzzle #3:
This puzzle has no final configuration.

 

这题折腾死我了,趟无数坑……想哭

翻了别人博客,拿到机器跑发现一堆问题,还是自己老实写吧。

分析:

直接模拟就行了,但是要小心处理输入输出

坑1:用gets()读取一行字符,如果最后一个字符恰好为空格,那么这一行最后的空格不会存入到数组,原本空格的位置被填入'\0'

坑2:输入Z结束输入,如果期间输入换行或者是空格,需要忽略这一次输入

 

由于我都是用gets处理每行的输入,第一行如果是换行的话那么gets(a[0])里面的值应该是'\0',而不是'\n',这个是我一直没有注意到的,然后卡这个位置很长时间,处理不了输入Z结束,然后遇到坑1了,用codeblock看不出来bug在哪里,当时没有想到是记录空格的位置出错了,后来我直接拿VS单步执行才发现这个(是看了这位大神的博客这才在用VS debug时候想起了原来他说的是这里的坑)。

 

#include 

int main ()
{

    int cas = 0;
    while(1)
    {
        char ch[5][5] = {};
        char c;
        gets(ch[0]);

		if(ch[0][0] == '\0') continue;
        if(ch[0][0] == 'Z')
            break;


        int x, y;
        for(int i = 1; i < 5; i++)
            gets(ch[i]);

        for(int i = 0; i < 5; i++)
        {
            for(int j = 0; j < 5; j++)
            {
                if(ch[i][j] == ' ' || ch[i][j] == '\0')
                {
                    x = i, y = j;
                }
            }

        }
//        printf("\n");
//        for(int i = 0; i < 5; i++)
//        {
//            for(int j = 0; j < 5; j++)
//            {
//                printf(j == 4 ? "%c\n" : "%c ", ch[i][j] );
//            }
//        }
//        printf("x = %d\t\ty = %d\n", x, y);

        int flag = 0;
        while(1)
        {
            c = getchar();
            if(c == '0')
                break;
            if(c == '\n')
                continue;
            switch(c)
            {
            case 'A':
                if(x-1 < 0)
                {
                    flag  = 1;
                    break;
                }
                ch[x][y] = ch[x-1][y];
                ch[x-1][y] = ' ';
                x--;
                break;
            case 'B':
                if(x+1 > 4)
                {
                    flag = 1;
                    break;
                }
                ch[x][y] = ch[x+1][y];
                ch[x+1][y] = ' ';
                x++;
                break;
            case 'R':
                if(y+1 > 4)
                {
                    flag = 1;
                    break;
                }
                ch[x][y] = ch[x][y+1];
                ch[x][y+1] = ' ';
                y++;
                break;
            case 'L':
                if(y-1 < 0)
                {
                    flag  = 1;
                    break;
                }
                ch[x][y] = ch[x][y-1];
                ch[x][y-1] = ' ';
                y--;
                break;
            }


        }
        if(cas)
            printf("\n");
        printf("Puzzle #%d:\n", ++cas);
        if(flag)
        {
            printf("This puzzle has no final configuration.\n");
            continue;
        }
        else
        {
            for(int i = 0; i < 5; i++)
            {
                for(int j = 0; j < 5; j++)
                {
                    printf(j == 4 ? "%c\n" : "%c ", ch[i][j] );
                }
            }
        }

        getchar();

    }

    return 0;
}

/*
ABCDE
FGHIJ
KLMNO
PQRS
TUVWX
AAAAABBRRRLL0
Z
*/

算法竞赛入门经典 第三章部分题解_第5张图片

 

你可能感兴趣的:(算法入门)