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

3-7 DNA序列 UVa1368

input: 
rows, cols


TATGATAC
TAAGCTAC
AAAGATCC
TGAGATAC
TAAGATGT


output:
TAAGATAC
程序如下:
#include <iostream>
#include <vector>


using namespace std;


typedef vector<char> char_1vec;
typedef vector< char_1vec > char_2vec;


void userMatrixIn(int, char_2vec&);
void all_DNA_seq(const int, char_2vec&);
int computeDist(const char_1vec&, const char_1vec&);
int computeSumDist(const char_2vec&, const char_1vec&);
int getMinVec(const char_2vec&);
void print_vec(const char_1vec&);
void print_mat(const char_2vec&);


int main()
{
    int m, n; // m个长度为n的序列
    cin >> m >> n;


    // 得到用户输入的矩阵
    char_2vec ch_matrix;
    userMatrixIn(n, ch_matrix);
    //cout << "user input matrix is: " << endl;
    //print_mat(ch_matrix);




    // 得到所有可能得DNA序列
    const int len(n);
    char_2vec dna_mat;
    all_DNA_seq(len, dna_mat);
    //cout << "all the DNA sequence is: " << endl;
    //print_mat(dna_mat);


    //int min_dist = numeric_limits<int>::infinity();
    int min_dist = 1001;
    //cout << "initial min dist is: " << min_dist << endl;
    char_2vec::const_iterator iter = dna_mat.begin();
    int thedist;
    char_2vec min_dist_vec;
    for (; iter!=dna_mat.end(); ++iter) {
        thedist = computeSumDist(ch_matrix, *iter);
        if (thedist<min_dist) {
            min_dist = thedist;
            min_dist_vec.clear();
            min_dist_vec.push_back(*iter);
        }
        else if (thedist==min_dist)
            min_dist_vec.push_back(*iter);
    }
    //cout << "min_dist is: " << min_dist << endl;
    //print_mat(min_dist_vec);
    int min_num = getMinVec(min_dist_vec);
    //cout << "min vec is in line: " << min_num << endl;
    print_vec(min_dist_vec[min_num]);
    return 0;
}


void userMatrixIn(int cols, char_2vec& matrix_in) {
    bool isstop = false;
    char ch;
    char_1vec vec_tmp;
    while (!isstop) {
        vec_tmp.clear();
        for (int i=0; i<cols; ++i) {
            cin >> ch;
            if (ch=='0') {
                isstop = true;
                break;
            }
            vec_tmp.push_back(ch);
        }
        matrix_in.push_back(vec_tmp);
    }
}


// input: length of DNA
// output: all the DNA sequence
// 千万不要返回局部变量的引用!
void all_DNA_seq(const int len, char_2vec& dna_2vec) {
    char dna[4] = {'A', 'C', 'G', 'T'};
    vector<int> a(len+1, 0);
    int n;
    vector<char> tmp;
    for (a[0]=0; a[0]<4;){
        tmp.clear();
        for (int i=len-1; i>=0; i--)
            tmp.push_back(dna[a[i]]);
        dna_2vec.push_back(tmp);
        n = 0;
        while (a[len] == 0)
            if (a[n] == 3)
                a[n++] = 0;
            else {
                a[n]++;
                break;
            }
        if (a[len] == 1)
            break;
    }
}


int computeDist(const char_1vec& ch1, const char_1vec& ch2) {
    int dist(0);
    vector<char>::size_type l = ch1.size();
    for (vector<char>::size_type i=0; i<l; ++i) {
        if (ch1[i]!=ch2[i])
            ++dist;
    }
    return dist;
}


int computeSumDist(const char_2vec& in_vec, const char_1vec& ch2) {
    int sum(0);
    char_2vec::const_iterator it = in_vec.begin();
    for (; it!=in_vec.end(); ++it)
        sum += computeDist(*it, ch2);
    return sum;
}


int getMinVec(const char_2vec& mat_in) {
    int num;
    char_1vec min_vec(mat_in[0]);
    char_2vec::const_iterator it = mat_in.begin();
    for (; it!=mat_in.end(); ++it) {
        if (*it <= min_vec) {
            min_vec = *it;
            num = it - mat_in.begin();
        }
    }
    return num;
}


void print_mat(const char_2vec& mat_in) {
    char_2vec::const_iterator it = mat_in.begin();
    for (; it!=mat_in.end(); ++it)
        print_vec(*it);
}


void print_vec(const char_1vec& vec_in) {
    char_1vec::const_iterator it = vec_in.begin();
    for (; it!=vec_in.end(); ++it)
        cout << *it << " ";
    cout << endl;
}
我的感想:
1 编写程序,首先要确定所有的功能模块,每个模块要做一件什么事情,确定需要的函数;
2 根据功能确定需要的数据结构,寻找相应的C++工具,最后最好能用typedef加一个别名;
3 vector的初始化:1 vector a(b),用b的副本初始化a; 2 vector a(num, ele), 用num个元素ele初始化vector,
如果是二维vector,则每个ele都是一个vector;3 vector a,如此定义的是一个空的vector,比如vector<vector T> a,
a.resize(num)得到的就是有num个空容器的二维容器,如果在调用push_back,会在num后面添加一维容器;
4 编写循环程序,就是:由特殊到一般的归纳法思维,如本例中产生所有DNA序列的程序;
5 绝对不能返回对局部对象的引用!
6 输出二维容器的所有元素,用两层iterator! 
7 vec1 = vec2, 将vec2的值赋给vec1,实际过程:在赋值前先将vec1清空!vec1>vec2,则是将vec1和vec2中的元素依次比较,和string中的比较规则一致;
实际上我这里得到输出的第一个容器已经是最小的vec了,故无需调用该函数。
8 注意本程序中二维数组的输入!每次vec_tmp都有一个清空操作!

3-8 UVa202 循环小数

输入被除数和除数,求出其小数点表示,无限循环用(循环节)表示

input:
5 43
output:
0.(116279069767441860465)
程序如下:

#include <iostream>
#include <vector>
#include <algorithm>


using namespace std;
typedef vector<int> int_1vec;
typedef vector< vector<int> > int_2vec;


int computeNum(int);
void getNtimes(int&, int);


int main() {
    int a(20), b(7), m, n(b), zheng(0); // a:被除数, b:除数, m:商, n:余数
    cout << "please input a and b: " << endl;
    while (cin >> a) {
        if (a==0)
            break;
        cin >> b;
        if (a>b) {
        zheng = a/b;
        a = a%b;
        }
        else
            zheng = 0;


        int b_num = computeNum(b);


        int a_num, num_diff, numZero;
        bool isloopend = false;
        int_1vec yushu_vec(1, a), tmp_vec;
        int_2vec shang_vec;
        while (!isloopend) {
            tmp_vec.clear();
        // 求得a和b
           // a后面补零使其与b的位数相同,如果a>=b,则完成。否则再补一个零
           // 1 求得a和b的位数
           // 2 补n个零
            a_num = computeNum(a);
            num_diff = b_num - a_num;
            numZero = num_diff - 1; // 要补零的个数比位数之差小1
            getNtimes(a, num_diff);
            if (a<b) {
                a = a*10;
                ++numZero;
            }
            tmp_vec.insert(tmp_vec.begin(), numZero, 0);
            // 由m、n求商和余数,如果余数在与之前的余数相同,则结束循环,否则循环继续
            m = a/b;
            tmp_vec.push_back(m);
            shang_vec.push_back(tmp_vec);
            n = a%b;
            int_1vec::iterator pos= find(yushu_vec.begin(), yushu_vec.end(), n);
            if (pos==yushu_vec.end()) {
                yushu_vec.push_back(n);
                a = n;
            }
            else {
                isloopend = true;
                // 输出没有循环的部分
                cout << zheng << "." << flush;
                int dist = pos - yushu_vec.begin();
                int_2vec::const_iterator it=shang_vec.begin();
                for (; it!=shang_vec.begin()+dist; ++it) {
                    int_1vec::const_iterator iter = (*it).begin();
                    for (; iter!=(*it).end(); ++iter)
                        cout << *iter << "";
                }
            // 输出循环的部分,用括号括起来
            cout << "(" << flush;
            //int dist = pos - yushu_vec.begin();
            it=shang_vec.begin()+dist;
            for (; it!=shang_vec.end(); ++it) {
                int_1vec::const_iterator iter = (*it).begin();
                for (; iter!=(*it).end(); ++iter)
                    cout << *iter << "";
                }
            cout << ")" << endl;
            }
        }
    }


    return 0;
}


int computeNum(int i) {
    int m = i, n, num(0);
    while (m!=0) {
        ++num;
        n = m%10;
        m = m/10;
    }
    return num;
}


void getNtimes(int& i, int n) {
    while (n) {
        i = i*10;
        --n;
    }
}
按照3-7的思维方式,此题在较短时间就做出来了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值