【大致题意】排列多个DNA序列,按照每个序列的“有序程度”。如果一个序列已经按照字母顺序排好了,那么这个序列有序程度最高,如AACCGGTT。反之,如果一个序列越无序,那么它的有序程度越低,如TGTCAA。
【解题思路】计算每个序列的“逆序数”,即反序字母对的个数,如ATGC的逆序数是3,因为TG,TC,GC都是逆序的。然后按照每个序列的逆序数排序,逆序数越大说明这个序列越无序。
#include <iostream> #include <algorithm> using namespace std; const int SIZEN = 51; const int SIZEM = 101; struct S{ char sequence[SIZEN]; int unsortedness; } DNA[SIZEM]; int n, m; int cnt[4]; //保存当前字母'A''C''G''T'的个数 enum {LETTERA, LETTERC, LETTERG, LETTERT}; bool cmp(S a, S b) { return a.unsortedness < b.unsortedness; } int main() { int i, j; while (cin >> n >> m) { cin.get(); for (i = 0; i < m; i++) { cin.getline(DNA[i].sequence, SIZEN); } for (i = 0; i < m; i++) { memset(cnt, 0, sizeof(cnt)); for (j = 0; j < n; j++) { if (DNA[i].sequence[j] == 'A') { cnt[LETTERA]++; DNA[i].unsortedness += cnt[LETTERC]; DNA[i].unsortedness += cnt[LETTERG]; DNA[i].unsortedness += cnt[LETTERT]; } else if (DNA[i].sequence[j] == 'C') { cnt[LETTERC]++; DNA[i].unsortedness += cnt[LETTERG]; DNA[i].unsortedness += cnt[LETTERT]; } else if (DNA[i].sequence[j] =='G') { cnt[LETTERG]++; DNA[i].unsortedness += cnt[LETTERT]; } else { cnt[LETTERT]++; } } } stable_sort(DNA, DNA+m, cmp); for (i = 0; i < m; i++) { cout << DNA[i].sequence << endl; } } return 0; }
【代码说明】定义了一个结构体数组来保存输入的多个DNA序列,并且每个序列对应一个整型值unsortedness来保存其逆序数,然后按照逆序数排序。
【个人体会】只是由于太久没有编程,生疏了,卡在了两个语法上。
其一是字符串的读取,C和C++有一系列的字符串读取方法,很难记住他们之间的区别,而我又一直纠结于代码写成C风格的还是C++风格的,不情愿两者混乱在一起,强迫症地逼自己尽量用C++的库函数(这使我吃了不少苦头啊)。
这道题虽然花了很长的时间,但是还是有收获的,最起码知道怎样读取一行字符串了(包括空格),既然我习惯用cin和cout,那么为保持一致,我使用cin的成员函数get和getline来读取单个字符和一行字符。需要注意的是,cin>>n之后如果使用cin.getline(),千万记住须先用cin.get()把cin>>n留在输入流中的换行符读掉,不然的话cin.getline()直接就读到了cin>>n遗留的换行符,而导致我们想要的读取的字符串没被读取。
其二是sort()函数的调用,起初我是这样 stable_sort(DNA[0], DNA[m], cmp); 调用的,结果编译出现错误,还以为是结构体或是比较函数写得有问题,查了好久,差点把数组改成了vector,因为看到API上是用迭代器作为参数的,后来改成 stable_sort(DNA, DNA+m,
cmp); 竟然可以了。
POJ_1007:DNA Sorting解题报告