//法一
//这题算是初等贪心的思路了,要求总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;
}