算法竞赛入门经典(第二版)第3章部分学习实现(上)

本文介绍了《算法竞赛入门经典(第二版)》第3章的两个实战题目——UVa1586 分子量和 UVa1225 数数字的解题思路与实现,帮助读者掌握基础算法应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

3-1 UVa1585 得分
Sample Input 
5 
OOXXOXXOOO 
OOXXOOXXOO 
OXOXOXOXOXOXOX 
OOOOOOOOOO 
OOOOXOOOOXOOOOX


Sample Output 
10 
9 
7 
55 
30
代码如下:
#include <iostream>
#include <string>


using namespace std;


int main()
{
    int T(0);
    string instr;


    cin >> T;
    int len(0);
    for (int i=0; i<T; i++){
        cin >> instr; //getline wrong
        len = instr.size();


        int num(0), sum(0);
        char ch;
        for (int j=0; j<len; j++){
            ch = instr[j];
            if (ch == 'O')
                num++;
            else
                num = 0;
            sum += num;
        }
        cout << sum << endl;
    }
    return 0;
}
我的感想:
输入的意思是:输入5后,输入一串字符串,马上有结果输出,再输入字符串,又有结果输出,
当输入5个字符串输出结果后时,程序退出。建议一定要在UVaOJ网站上注册提交!!


3-2 UVa1586 分子量

Sample Input 
4 
C 
C6H5OH 
NH2CH2COOH 
C12H22O11

Sample Output 
12.010 
94.108 
75.070 
342.296
代码如下:
#include <iostream>
#include <string>
#include <iomanip>
#include <stack>


using namespace std;


int main()
{
    int T;
    cin >> T;


    string instr;
    int num(0), num0;
    char ch;
    float seoul_value(0), sum(0);
    stack<char> ch_stack;


    for (int i=0; i<T; i++){
        cin >> instr;
        string::iterator it = instr.begin();
        while (it != instr.end()){
            //cout << "it point to: " << *it << endl;
            switch (*it) {
                case 'C':
                    seoul_value = 12.01;
                    break;
                case 'H':
                    seoul_value = 1.008;
                    break;
                case 'O':
                    seoul_value = 16.00;
                    break;
                case 'N':
                    seoul_value = 14.01;
                    break;
            }
            //cout << "seoul_value is: " << seoul_value << endl;
            char t;
            while (1){
                t = *(++it);
                if (t>='0' && t<='9')
                    ch_stack.push(t);
                else {
                     it--;
                     break;
                }
            }
            if (ch_stack.empty())
                num = 1;
            else {
                int tmp = 1;
                num = 0; // important
                while (!ch_stack.empty()){
                    ch = ch_stack.top();
                    num0 = ch - '0';
                    num += num0 * tmp;
                    ch_stack.pop();
                    tmp = tmp * 10;
                }
            }
            sum += num * seoul_value;
            it++;
        }
        cout << setprecision(3) << fixed;
        cout << sum << endl;
        cout.unsetf(ostream::floatfield);
        sum = 0, num = 0;
    }
    return 0;
}
我的感想:
1 switch case的使用,要有break才行;
2 自加、自减一定要慎用,我觉得应该尽量避免;
3 考虑问题不够全面,比如出现数字12、123的现象;
4 用作局部统计的变量在某次使用完后一定记得置0!在第53行!花了我好长时间排错!
5 如何判断两个字符间的数字,我想到的只有stack、还有更好的办法吗?
6 输入字符'8',输出整数8,直接用字符减去'0'即可,by the way,'0'对应的整数是48;
7 先写伪代码理清思路,很重要啊!


 3-3 UVa1225 数数字

输入一个数n,把前n个整数按12^1112……顺序写在一起,统计1~9分别出现的次数 
#include <iostream>

using namespace std;


//数字较大时要在函数外面声明!
int arr[10000][10] = {};


int main()
{
    //对每个数输出组成它的每个数字,存储到数组中
    int n, x, y, T;
    for (int i=1; i<=10000; ++i){
        x = i;
        while (x){
            y = x % 10;
            x = x / 10;
            arr[i][y]++;
        }
        for (int j=0; j<10; ++j)
            arr[i][j] += arr[i-1][j];
    }


    cin >> T;
    while (T--){
        cin >> n;
        for (int i=0; i<9; i++)
            cout << arr[n][i] << " ";
        cout << arr[n][9];
        if (T>0)
            cout << endl;
    }
    return 0;
}

另外:实现了000到100的程序
#include <iostream>

using namespace std;

int main()
{
    int a[3] = {};
    int n;
    for (a[0]=0; a[0]<10;){
	for (int i=2; i>=0; i--)
            cout << a[i] << " ";
        n = 0;
        while (a[2] == 0)
            if (a[n] == 9)
                a[n++] = 0;
            else {
                a[n]++;
                break;
            }
        cout << endl;
        if (a[2] == 1)
            break;
    } 
    return 0;
}

// 习题3-4 UVa445 
如果一个字符串可以由某个长度为k的字符串重复多次得到(比如这里的2次),则称该串以k
为周期;输入一个长度不超过80的字符串,输出其最小周期。
input:
abcabcabcabc

output:
3

// 我还没做出来,没有结果输出
程序如下:
#include <iostream>
#include <string>
#include <vector>
#include <queue>


using namespace std;


int main()
{
    int t = 1;
    cin >> t;


    string str;
    while (t--){
        // process every string
        cin >> str;
        vector<char> vec1;
        queue<char> q2;
        vector<char>::size_type size_vec1;
        queue<char>::size_type size_q2;
        char tmp;
        for (string::size_type i=0; i<str.size(); ++i){
            if (i==str.size()-1){
                cout << "the circle maybe the lenghth of whole string!" << endl;
                break;
            }


            // if diff from vector1[0], vector1.push
            if (vec1.empty() || str[i]!=vec1[0]) {
                vec1.push_back(str[i]);
                continue;
            }


            // else push to vector2, and compare the coming char
            else {
                size_vec1 = vec1.size();
                for (vector<char>::size_type j=0; j<size_vec1; ++j){
                    if (str[i] == vec1[j]) {
                        q2.push(str[i]);
                        i++ ;
                    }
                    else {
                        while (!q2.empty()){
                            tmp = q2.front();
                            vec1.push_back(tmp);
                            q2.pop();
                        }
                        vec1.push_back(str[i]);
                        break;
                    }
                }
                if (q2.size() == size_vec1) {
                    cout << "the circle is: " << size_vec1 << endl;
                    break;
                }
            }
            //vec3.clear();
        }
        vec1.clear();
    }
}


3-5 UVa227 谜题
#include <iostream>
#include <vector>


using namespace std;
typedef vector< vector<char> > char_vec;


void getLocate(const char_vec&, int&, int&);
bool moveLocate(char_vec&, int&, int&, char);


int main()
{
    char ch[25] = {'T', 'R', 'G', 'S', 'J', 'X', 'D', 'O', 'K', 'L', 'M', ' ', 'V', 'L', 'N', 'W',
    'P', 'A', 'B', 'E', 'U', 'Q', 'H', 'C', 'F'};
    vector< vector<char> > ch_vec;
    ch_vec.resize(5);
    for (int i=0; i<5; ++i)
        for (int j=0; j<5; ++j)
            ch_vec[i].push_back(ch[i*5+j]);
    int m, n; 
    getLocate(ch_vec, m, n);


    bool flag(true);
    char ch_cin;
    while (cin>>ch_cin) {
        cout << "m,n= " << m << " " << n << endl;
        flag = moveLocate(ch_vec, m, n, ch_cin);
        if (flag==false)
            break;
    }
    getLocate(ch_vec, m, n);
    cout << "m= " << m << endl;
    cout << "n= " << n << endl;


    for (int i=0; i<5; ++i) {
        for (int j=0; j<5; ++j)
            cout << ch_vec[i][j] << " ";
        cout << endl;
    }
    return 0;


}


void getLocate(const char_vec& in_char_vec, int& x, int& y) {
    for (int i=0; i<5; ++i)
    for (int j=0; j<5; ++j) {
        if (in_char_vec[i][j]==' ') {
            x = i;
            y = j;
        }
    }
}


bool moveLocate(char_vec& in_char_vec, int& x, int& y, char in_ch) {
    char tmp;
    if (in_ch=='A') {
        if (x==0) {
            cerr << "This puzzle has no final configuration." << endl;
            return false;
        }
        else {
            tmp = in_char_vec[x][y];
            in_char_vec[x][y] = in_char_vec[x-1][y];
            in_char_vec[--x][y] = tmp;
            return true;
        }
    }
    else if (in_ch=='B') {
        if (x==4) {
            cerr << "This puzzle has no final configuration." << endl;
            return false;
        }
        else {
            tmp = in_char_vec[x][y];
            in_char_vec[x][y] = in_char_vec[x+1][y];
            in_char_vec[++x][y] = tmp;
            return true;
        }
    }
    else if (in_ch=='L') {
        if (y==0) {
            cerr << "This puzzle has no final configuration." << endl;
            return false;
        }
        else {
            tmp = in_char_vec[x][y];
            in_char_vec[x][y] = in_char_vec[x][y-1];
            in_char_vec[x][--y] = tmp;
            return true;
        }
    }
    else if (in_ch=='R') {
        if (y==4) {
            cerr << "This puzzle has no final configuration." << endl;
            return false;
        }
        else {
            tmp = in_char_vec[x][y];
            in_char_vec[x][y] = in_char_vec[x][y+1];
            in_char_vec[x][++y] = tmp;
            return true;
        }
    }
    else {
        cout << "to the end!" << endl;
        return false;
    }
    return false;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值