首页 > 代码库 > POJ_1007:DNA Sorting解题报告

POJ_1007:DNA Sorting解题报告

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