算法竞赛入门经典(第二版)-刘汝佳-第四章 函数与递归 例题+习题(15/16)

说明

本文是我对第四章题目的练习总结,建议配合紫书——《算法竞赛入门经典(第2版)》阅读本文。
另外为了方便做题,我在VOJ上开了一个contest,欢迎一起在上面做:第四章contest
如果想直接看某道题,请点开目录后点开相应的题目!!!

例题

例4-1 UVA 1339 古老的密码

思路
只需要分别统计两个字符串中26个字母出现的个数,然后对统计数组做一个排序,如果一样则结果为YES。
详细解释见书P73。
代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int main(void)
{
    int n[2], cnt[2][26];
    char s[2][101];
    while (cin >> s[0] >> s[1]) {
        memset(cnt, 0, sizeof(cnt));
        for (int i = 0; i < 2; i ++) {
            n[i] = strlen(s[i]);
            for (int j = 0; j < n[i]; j ++)
                cnt[i][s[i][j]-'A'] ++;
            sort(cnt[i], cnt[i]+26);
        }

        bool flag = true;
        for (int j = 0; j < 26; j ++)
            if (cnt[0][j] != cnt[1][j]) flag = false;
        printf("%s\n", flag ? "YES" : "NO");
    }

    return 0;
}

例4-2 UVA 489 刽子手游戏

思路
给定两个字符串,第一个串是用来匹配的,从第二个串的第一个字符开始匹配,如果第二个串中的字符在第一个串出现,则表示猜中了,第一个串中的相同的那个字符都算被猜中;如果没有出现则表示猜错,同样的猜错只算一次。在整个匹配的过程中,如果在还没猜错7次之前,第一个串中所有的字符都被猜完了, 则输出“You win.”,如果你还没全部猜完的时候就已经猜错7次,则输出“You lose.”。如果整个匹配过程结束后,你没赢也没输,则输出“You chickened out.”。
这个题需要注意的细节很多,我WA了多次。在这里提供一组测试数据吧,希望对一直WA的同学有用。
测试数据来源:uva489讨论

INPUT:
1
cheese
chese
2
cheese
abcdefg
3
cheese
abcdefgij
4
rommel
romlnptuyq
5
rommel
romlnptuyqw
6
casa
ca
7
otorrinolaringologia
otr
8
peru
abcdefghijklmno
9
lastima
la
10
aaaaaaaaaaaaaaaaaaaaaa
a
11
bobobobobobobo
b
12
lalalalabababababaaaaa
alhhhhhhhhhhhhhhhhhhhhhhh
13
lkjaskljfkjklsalsdjfslkjfjf
dfklsdfskld
14
nbmbmmbnbbmbmbmbmnbnbnbmbmmbbnbnnbmbmbmboffiifififififfiif
ppppppppppppppppppppppppppppppppppwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwweeeeeeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrb
15
abcdefggegegegegegege
gegegegegddabacecevbbdbdnndnenjejje
16
diccionariosdeportugues
dcptgiowqqqaazzxxxx
17
b
c
18
kljfdsjfoieoijefnvnenvionewveinvewv
dkdjjshue
19
ooooooooooooopppppppppppppppppppppeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrwwwwwwwwwwwwwwwwwwwtttttttttttttttttt
operwt
20
ooooooooooooopppppppppppppppppppppeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrwwwwwwwwwwwwwwwwwwwtttttttttttttttttt
operwqzxcvbnmklo
21
ploploploploploploploploploploploploploploploploploploploploploploploploploploploploploploploploploploploploploploplo
jslkfsdjfsjfljfsdjfkdsjkjflkf
22
añoañoañoañoañoañoañoañoañoañoañoañoañoañoañoperuperuperuperuperuperuperuperuperuañoañoañoañoañoañoañoañoañoaño
añoperu
23
añoañoañoañoañoañoañoañoañoañoañoañoañoañoañoperuperuperuperuperuperuperuperuperuañoañoañoañoañoañoañoañoañoaño
ududududuudududupepeppewguqwhuihewhepqwehuwehwmncvmnnvmnvcnb
4
t
r
1
aaa
bcdbcdbcdbcdefghja
7
aaa
bcdbcdbcdbcdefdta
2
aaa
bcdbcdbcdbcdegt
1
cheese
ch
1
z
abcdef
1
aaa
bcdbcdbcdbcdefghja
7
aaa
bcdbcdbcdbcdefdta
2
aaa
bcdbcdbcdbcdegt
167
axyq
eprxibexxyf
171
nho
tonpyzwotkg
1
z
abcdef
1
abcdef
aghijklmcdefb
2
abcdef
abcdklmnoegfi
3
abcdef
abcklmnopdf
-1

OUTPUT:
Round 1
You win.
Round 2
You chickened out.
Round 3
You lose.
Round 4
You chickened out.
Round 5
You lose.
Round 6
You chickened out.
Round 7
You chickened out.
Round 8
You lose.
Round 9
You chickened out.
Round 10
You win.
Round 11
You chickened out.
Round 12
You chickened out.
Round 13
You chickened out.
Round 14
You chickened out.
Round 15
You chickened out.
Round 16
You chickened out.
Round 17
You chickened out.
Round 18
You chickened out.
Round 19
You win.
Round 20
You lose.
Round 21
You chickened out.
Round 22
You win.
Round 23
You lose.
Round 4
You chickened out.
Round 1
You lose.
Round 7
You win.
Round 2
You chickened out.
Round 1
You chickened out.
Round 1
You chickened out.
Round 1
You lose.
Round 7
You win.
Round 2
You chickened out.
Round 167
You chickened out.
Round 171
You lose.
Round 1
You chickened out.
Round 1
You lose.
Round 2
You win.
Round 3
You chickened out.

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int main(void)
{
    int rnd;
    int used[26];
    char s[1000];
    while (cin >> rnd && rnd != -1) {
        memset(used, 0, sizeof(used));
        scanf("%s", s);
        int len = strlen(s);
        for (int i = 0; s[i]; i ++)
            used[s[i]-'a'] ++;

        int wrong = 0;
        scanf("%s", s);
        for (int i = 0; s[i]; i ++) {
            if (used[s[i]-'a']) {
                len -= used[s[i]-'a'];
                used[s[i]-'a'] = 0;
            } else
                wrong ++;
            if (wrong == 7 || len == 0) break; 
        }

        printf("Round %d\n", rnd);
        if (wrong == 7)
            printf("You lose.\n");
        else if (len <= 0)
            printf("You win.\n");
        else
            printf("You chickened out.\n");
    }

    return 0;
}

例4-3 UVA 133 发放救济金

思路
这个题没什么复杂度,就只是模拟。注意go函数可以把顺时针和逆时针统一起来的巧妙方法。
代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int n, k, m;
int person[20];

int go(int s, int d, int p)
{
    while (d--) {
        do {
            s = (s+p+n) % n;
        } while (!person[s]);
    }
    return s;
}

int main(void)
{
    while (cin >> n >> k >> m, n || k || m) {
        memset(person, 1, sizeof(person));
        int left = n;
        int a = n-1, b = 0;
        while (left) {
            a = go(a, k, 1);
            b = go(b, m, -1);
            if (left < n) printf(",");
            printf("%3d", a+1);
            person[a] = 0;
            left --;
            if (person[b]) {
                printf("%3d", b+1);
                person[b] = 0;
                left --;
            }
            if (left == 0) break;
        }
        printf("\n");
    }

    return 0;
}

例4-4 UVA 213 信息解码

思路
主要考察两个知识点:getchar()读入,以及二进制与十进制的互相转换。
同时,频繁使用的或者模块性很强的功能写成函数,的确能使代码精简很多。
代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 7;
const int M = 1<<(N+1);

char head[M];
int bi[N+1];

void init()
{
    bi[1] = 0;
    int fact = 1;
    for (int i = 1; i < 7; i ++) {
        fact <<= 1;
        bi[i+1] = bi[i] + fact - 1;
    }
}

int get01()
{
    char c;
    while ((c = getchar()) == '\n');
    return c-'0';
}

int getMsg(int len)
{
    int res = 0;
    while (len --)
        res = 2*res + get01();
    return res;
}

char decode(int msg, int len)
{
    return head[bi[len]+msg];
}

int main(void)
{
    init();
    while (gets(head)) {
   
  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值