UVA - 1368 DNA Consensus String
//法一 //这题算是初等贪心的思路了,要求总harmming距离最小,通过使每一位上选取的字母,都能使该位对总harming距离的贡献最小,按照定义,也就是所有DNA在该位置上,ATCG字母究竟哪个最多,若多个最多,就选字典序小的...思路确实挺巧妙,值得琢磨 //顺带提一下,不知道为什么,看了别人的代码,发现有人将变量作为数组维度,即在main函数内部,char DNA[m][n+1];时,居然能AC,不是说数组的维度只能是常量吗?
#include <bits/stdc++.h> using namespace std; const int N = 1005; const int M = 50; char DNA[M][N]; int num[4]; int main() { int t, m, n; //m是数目,n是长度 cin >> t; while (t--) { int sum = 0; cin >> m >> n; // char DNA[m][n+1]; for (int i = 0; i < m; i++) cin >> DNA[i]; for (int i = 0; i < n; i++) { memset(num, 0, sizeof(num)); for (int j = 0; j < m; j++) switch(DNA[j][i]) { case 'A' :num[0]++;break; case 'C' :num[1]++;break; case 'G' :num[2]++;break; case 'T' :num[3]++;break; } int temp = num[0], ans = 0; for (int j = 1; j < 4; j++) { if (num[j] > temp) { ans = j; temp = num[j]; } } sum += m - temp; switch(ans) { case 0: cout << "A";break; case 1: cout << "C";break; case 2: cout << "G";break; case 3: cout << "T";break; } } cout << endl << sum << endl; } return 0; }
/* 法二: 用结构体真的能让代码简单很多很多... 这个思路有个比较巧妙的地方,在于:将Harming距离所要求的,与对应字符不同的字符个数,转换为与对应字符相同的个数,然后再用总数(DNA个数)减去相同的个数 其实不用这个思路也可以,但是会比较繁琐,例如我假设最终求得的那个DNA的,某个位置是A,那么所有m条DNA,对于每一条而言,如果对应的这个位置不是A,那么这个位置对应的G\C\T都要加1,繁琐且易错...而如果转变思路,用m减去相同的,需要更新的就只有该位置的A (这种思路下,记录的就是,当前位置下,ATCG分别会和几条DNA的该位置,对总harming距离作出贡献,这就真的是取最小值了) */
#include <bits/stdc++.h> using namespace std; const int N = 1005; char check[N]; char ans[N]; struct DNA { int a, c, g, t; void clearall() { a = c = g = t = 0; } int getmax(char& ch)//此处很多地方要用偏序的不等号,因为有多个答案时,要输出字典序最小的...一开始忘了=号,结果答案错 { ch = ( max(a, c) >= max(g, t) ? (a >= c? 'A':'C'):(g >= t? 'G' : 'T') ); return max( max(a, c), max(g, t) ); } }dna[N]; int main() { int t, m, n; //m是数目,n是长度 cin >> t; while (t--) { int sum = 0; cin >> m >> n; for (int i = 0; i < n; i++) dna[i].clearall();//一定是按照位置清空的,也就是DNA长度,而不是DNA数 for (int i = 0; i < m; i++) { cin >> check; for (int j = 0; j < n; j++) switch(check[j]) { case'A': dna[j].a++;break; case'G': dna[j].g++;break; case'C': dna[j].c++;break; case'T': dna[j].t++;break; } } for (int i = 0; i < n; i++) { sum += m - dna[i].getmax(ans[i]); } ans[n] = '\0'; cout << ans << endl << sum << endl; } return 0; }