签到,今天是连续OJ系列的第13天
题目
输入m个长度均为n的DNA序列, 求一个DNA序列, 到所有序列的总Hamming距离尽量小。 两个等长字符串的Hamming距离等于字符不同的位置个数, 例如, ACGT和GCGA的Hamming距离为2( 左数第1, 4个字符不同) 。
输入整数m和n( 4≤m≤50, 4≤n≤1000) , 以及m个长度为n的DNA序列( 只包含字母A, C, G, T) , 输出到m个序列的Hamming距离和最小的DNA序列和对应的距离。 如有多解, 要求为字典序最小的解。 例如, 对于下面5个DNA序列,
TATGATAC
TAAGCTAC
AAAGATCC
TGAGATAC
TAAGATGT
最优解为TAAGATAC。
样例输入
3
5 8
TATGATAC
TAAGCTAC
AAAGATCC
TGAGATAC
TAAGATGT
4 10
ACGTACGTAC
CCGTACGTAG
GCGTACGTAT
TCGTACGTAA
6 10
ATGTTACCAT
AAGTTACGAT
AACAAAGCAA
AAGTTACCTT
AAGTTACCAA
TACTTACCAA
可以看出先输入一个数T,然后输入T组样例
样例输出
TAAGATAC
7
ACGTACGTAA
6
AAGTTACCAA
12
代码
import java.util.Scanner;
public class Uva1368 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner =new Scanner(System.in);
int m;
int n;
int T;
T=scanner.nextInt();
while(T-->0){
m=scanner.nextInt();
n=scanner.nextInt();
String []str=new String[m];
char [][]ch=new char[m][n];
for(int i=0;i<m;i++){
str[i]=scanner.next();
ch[i]=str[i].toCharArray();//转换成字符数组
}
int sum=0;
for(int i=0;i<n;i++){//一列一列的找
int []ACGT=new int[4];//用于存储'A','C','G','T'出现的次数
int max=0;
for(int j=0;j<m;j++){
if(ch[j][i]=='A'){
ACGT[0]=ACGT[0]+1;
}if(ch[j][i]=='C'){
ACGT[1]=ACGT[1]+1;
}if(ch[j][i]=='G'){
ACGT[2]=ACGT[2]+1;
}if(ch[j][i]=='T'){
ACGT[3]=ACGT[3]+1;
}
}
max=Math.max(Math.max(ACGT[0], ACGT[1]), Math.max(ACGT[2], ACGT[3]));//得到出现次数最多的数,如果有次数相同,也得到该数
sum+=m-max;//得到Hamming值
boolean flag=true;//不重复找,浪费时间
for(int k=0;k<4;k++){
if(ACGT[k]==max&&flag){//找到该数对应的下标,因为是从小到大查找的,即使max是相同的数得到的,也符合字典序
if(k==0){
System.out.print('A');
flag=false;
continue;
}if(k==1){
System.out.print('C');
flag=false;
continue;
}if(k==2){
System.out.print('G');
flag=false;
continue;
}if(k==3){
System.out.print('T');
flag=false;
continue;
}
}
}
}
System.out.println();
System.out.println(sum);
}
}
}
这个题是我直接一次就AC了的,首先思想很重要,怎样得到一个序列使得全部的DNA序列的总Hamming距离最小,如果一个一个的试,肯定会超时,既然要最小那么就要每一位的Hamming最小,即就是欲得到的字符应该是所有的DNA序列的当前位的字符出现次数的字符,这样的Hamming就会最小,一个字符串都是这种方法得到的话,就会得到总Hamming距离最小.好了,得到了方法,就好处理了.如果是有相同次数的字符的话,也可以处理,具体的实现我写进代码了,我觉得还是挺巧妙的.