【大致题意】排列多个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); 竟然可以了。