算法竞赛入门经典-第三章源代码

// 程序3-1 逆序输出
#include <stdio.h>
#define MAXN 100+10 // 保险
int a[MAXN]; // 比较大的数组应尽量声明在main函数外
int main(void)
{
    int i, x, n=0;
    while(scanf("%d", &x)==1)
        a[n++] = x;
    for(i = n-1; i >= 1; i--)
        printf("%d ", a[i]);
    printf("%d\n", a[0]); // 输出n个整数只需要n-1个空格,所以分两行输出
    return 0;
}

// 程序3-2 开灯问题
#include <stdio.h>
#include <string.h>
#define MAXN 1000 + 10
int a[MAXN]; // 数组模拟操作
int main(void)
{
    int i, j, n, k, first = 1;
    memset(a, 0, sizeof(a));
    scanf("%d%d", &n, &k); // 两个循环位置可以互换
    for(i = 1; i <= k; i++) // 遍历每个人
        for(j = 1; j <= n; j++) // 分析每盏灯
            if(j%i == 0)
                a[j] = !a[j];
    for(i = 1; i <= n; i++)
        if(a[i])
        {
            if(first) first = 0; // 避免输出多余空格
            else printf(" ");
            printf("%d", i);
        }
    printf("\n");
    return 0;
}

// 程序3-3 蛇形填数
#include <stdio.h>
#include <string.h>
#define MAXN 20
int a[MAXN][MAXN];
int main(void)
{
    int n, x, y, tot = 0;
    scanf("%d", &n);
    memset(a, 0, sizeof(a));
    tot = a[x=0][y=n-1] = 1; // 简洁高效 
    while(tot < n*n){ // 预判(越界或已填)并填入 // &&短路运算符保证不越界
        while(x+1<n && !a[x+1][y]) a[++x][y] = ++tot;
        while(y-1>=0 && !a[x][y-1]) a[x][--y] = ++tot;
        while(x-1>=0 && !a[x-1][y]) a[--x][y] = ++tot;
        while(y+1<n && !a[x][y+1]) a[x][++y] = ++tot;
    } // 使用++i不影响后面的数据
    for(x = 0; x < n; x++){
        for(y = 0; y < n; y++)
            printf("%5d", a[x][y]);
        printf("\n");
    }
    return 0;
}

// 程序3-4 竖式问题
#include <stdio.h>
#include <string.h>
int main(void)
{
    int i, ok, abc, de, x, y, z, count = 0;
    char s[20], buf[100];
    scanf("%s", s); // 用字符串存放整数,便于利用字符串函数
    for(abc = 111; abc <= 999; abc++) // 先穷举abc/de,后剔除不符合的
        for(de = 11; de <= 99; de++){ // 为什么从11/111开始?
            x = abc*(de%10);
            y = abc*(de/10);
            z = abc*(de);
            sprintf(buf, "%d%d%d%d", abc, de, x, y, z); // 创建“集合”
            ok = 1; // printf输出到屏幕,fprintf输出到文件,sprintf输出到字符串
            for(i = 0; i < strlen(buf); i++)
                if(strchr(s, buf[i]) == NULL) // “属于关系”
                    ok = 0;
            if(ok){
                printf("<%d>\n", ++count);
                printf("%5d\nX%4d\n-----\n%5d\n%4d\n-----\n%5d\n\n",
                       abc, de, x, y, z);
            }
        }
    printf("The number of solutions = %d\n", count);
    return 0;
}

// 程序3-5 最长回文子串(1)
#include <stdio.h>
#include <string.h>
#include <ctype.h> // 判断字符属性,转换字符
#define MAXN 5000+10
char buf[MAXN], s[MAXN];
int main(void)
{
    int i, j, k, ok, n, m=0, max=0;
    fgets(buf, sizeof(s), stdin);
    n = strlen(buf);
    for(i = 0; i < n; i++)
        if(isalpha(buf[i]))
            s[m++] = toupper(buf[i]);
    for(i = 0; i < m; i++)
        for(j = i; j < m; j++){ // 枚举所有子串(首i->尾j)
            ok = 1; // "判断题"
            for(k = i; k<=j&&ok!=0; k++)
                if(s[k] != s[i+j-k]) // 判断回文串
                    ok = 0;
            if(ok && j-i+1>max)
                max = j-i+1;
        }
    printf("max = %d\n", max);
    return 0;
}

// 程序3-6 最长回文子串(2) // 迭代式开发
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAXN 5000+10
char buf[MAXN], s[MAXN];
int p[MAXN];
int main(void)
{
    int i, j, x, y, n, m = 0, max = 0;
    fgets(buf, sizeof(s), stdin); // 读入一行字符串
    n = strlen(buf);
    for(i = 0; i < n; i++) // 预处理字符串简化任务
        if(isalpha(buf[i])){
            p[m] = i; // m对应新串序号,i对应原串序号
            s[m++] = toupper(buf[i]);
        }
    for(i = 0; i < m; i++)
    { // i为中间位置,j为“半径”,注意对j的限制(由特殊例子推导一般)
        for(j=0; i-j>=0&&i+j<m; j++){// 奇数序列
            if(s[i-j] != s[i+j])
                break;
            if(j*2+1 > max){
                max = j*2+1; // 记录当前最大值
                x = p[i-j]; // 记录原串起始(结束)位置
                y = p[i+j];
            }
        }
        for(j=0; i-j>=0&&i+j+1<m; j++){// 偶数序列
            if(s[i-j] != s[i+j+1])
                break;
            if(j*2+2 > max){
                max = j*2+2;
                x = p[i-j];
                y = p[i+j+1];
            }
        }
    }
    for(i = x; i <= y; i++)
        printf("%c", buf[i]);
    printf("\n");
    return 0;
}

// 习题3-1 分数统计(stat)
#include <iostream>
#include <cstring>
using namespace std;

int main(void)
{
    int a[101], n; // 用数组记录次数
    memset(a, 0, sizeof(a));
    while(cin >> n)
        ++a[n];
    int max = a[0];
    for(int i = 1; i < 101; ++i)
        if(a[i] > max)
            max = a[i];
    for(int i = 0; i < 101; ++i)
        if(a[i] == max)
            cout << i << " ";
    return 0;
}

// 习题3-1 分数统计(stat)
#include <iostream>
#include <algorithm> // 重要
#include <cstring>
using namespace std;
const int MAXN = 1000+10;

bool cmp(double a, double b)
{
    return 100*a<100*b;
}

int main(void)
{
    int a[MAXN];
    double mark[MAXN];
    memset(a, 0, sizeof(a));
   
    int n = 0;
    while(cin >> mark[n++]); // 记录数据及数目
    sort(mark, mark+n, cmp); // 排序预处理
   
    int cnt = 1;
    for(int i = 1; i < n; i++){ // 记录mark次数
        if(100*mark[i] == 100*mark[i-1]) // 为什么后面的与前面的比较?考虑最后一个数!
            cnt++;
        else{
            a[i-1] = cnt; // 标记到最后一个相同的数
            cnt = 1;
        }
    }
    a[n-1] = cnt;

    int max = a[0];
    for(int i = 1; i < n; i++) // 寻找最大次数
        if(a[i] > max)
            max = a[i];

    for(int i = 0; i < n; i++) // 从小到大依次输出
        if(a[i] == max)
            cout << mark[i] << " ";
   
    return 0;
}

// 习题3-2 单词的长度(word)
#include <iostream>
#include <cstring>
using namespace std;

int main(void)
{
    string line;
    int cnt, word;
    cnt = word = 0;
    while(cin >> line){
        ++word;
        cnt += line.size();
    }
    cout << 1.0*cnt/word << endl;
    return 0;
}

// 习题3-3 乘积的末3位(product)
#include <iostream>
using namespace std;

int main(void)
{
    int cheng, ge, shi, bai, n;
    cheng = 1;
    while(cin >> n){
        ge = cheng*(n%10);
        shi = 10*cheng*((n/10)%10);
        bai = 100*cheng*(n/100);
        cheng = ge + bai + shi;    // “小学生”算术
        cheng %= 1000;
    }
    cout << cheng << endl;
    return 0;
}

// 习题3-4 计算器(calculator)
#include <cstdio>
#include <iostream>
using namespace std;
const int MAXN = 100+10;

int main(void)
{
    char word[MAXN];
    int a, b, i;
    char c;
    while(1){
        i = 0;
        while(c=getchar(), c!='\n') // 巧用逗号运算符
            if(c!=' ' && c!='\t')
                word[i++] = c;
        sscanf(word, "%d%c%d", &a, &c, &b);
        switch(c){
            case '+': cout << a+b << endl; break;
            case '-': cout << a-b << endl; break;
            case '*': cout << a*b << endl; break;
        }
    }
    return 0;
}

// 习题3-5 旋转(rotate)
#include <iostream>
#define MAXN 10
using namespace std;

char s[MAXN][MAXN];
int main(void)
{
    int n;
    cin >> n;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
         cin >> s[i][j];
            cout << s[i][j] << " ";
        }
        cout << endl;
    }

    for(int j=n-1; j>=0; j--){
        for(int i=0; i<=n-1; i++)
            cout << s[i][j] << " ";
        cout << endl;
    }
    return 0;
}

// 习题3-6 进制转换1(base1)
#include <iostream>
#include <cstring>
using namespace std;

int main(void)
{
    int n, b, i, a[100];
    while(cin >> n >> b){
        i = 0;
        memset(a, 0, sizeof(a));
        while(n != 0)
        {
            a[i++] = n % b;
            n /= b;
        }
        for(int j=i-1; j>=0; j--)
            cout << a[j];
        cout << endl;
    }
    return 0;
}

// 习题3-7 进制转换2(base2)
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;

const int MAXN = 5000+10;
int main(void)
{
    int a[MAXN], b, n;
    while(cin >> b >> n)
    {
        int cnt = 0;
        memset(a, 0, sizeof(a));
        while(n)
        {
            a[cnt++] = n%10;
            n /= 10;
        }
        int sum = 0;
        for(int i = 0; i < cnt; ++i)
            sum += a[i]*pow(b, i);
        cout << sum << endl;
    }
    return 0;
}

// 习题3-8 手机键盘(keyboard)
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;

int main(void)
{
    string word;
    while(cin >> word){
        for(int i = 0; i < word.size(); ++i){
            int t = (word[i]-'a'+1)%3;
            if(abs(word[i]-word[i-1]) < 3 && i != 0)
                cout << word[i-1] << (t?t:3);
            else
                cout << word[i] << (t?t:3);
        }
        cout << endl;
    }
    return 0;
}

转载于:https://www.cnblogs.com/yanweicode/p/4356295.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值