POJ1007 DNA Sorting

题目:

Description

One measure of ``unsortedness'' in a sequence is the number of pairs of entries that are out of order with respect to each other. For instance, in the letter sequence ``DAABEC'', this measure is 5, since D is greater than four letters to its right and E is greater than one letter to its right. This measure is called the number of inversions in the sequence. The sequence ``AACEDGG'' has only one inversion (E and D)---it is nearly sorted---while the sequence ``ZWQM'' has 6 inversions (it is as unsorted as can be---exactly the reverse of sorted). 
You are responsible for cataloguing a sequence of DNA strings (sequences containing only the four letters A, C, G, and T). However, you want to catalog them, not in alphabetical order, but rather in order of ``sortedness'', from ``most sorted'' to ``least sorted''. All the strings are of the same length. 

Input

The first line contains two integers: a positive integer n (0 < n <= 50) giving the length of the strings; and a positive integer m (0 < m <= 100) giving the number of strings. These are followed by m lines, each containing a string of length n.

Output

Output the list of input strings, arranged from ``most sorted'' to ``least sorted''. Since two strings can be equally sorted, then output them according to the orginal order.

Sample Input

10 6
AACATGAAGG
TTTTGGCCAA
TTTGGCCAAA
GATCAGATTT
CCCGGGGGGA
ATCGATGCAT

Sample Output

CCCGGGGGGA
AACATGAAGG
GATCAGATTT
ATCGATGCAT
TTTTGGCCAA
TTTGGCCAAA
思路:

题目的意思就是求每个DNA序列的混乱度,再将序列以混乱度从小到大的顺序打印出来。关于混乱度的定义,description第一段已给出。我抖了个机灵,用了冒泡,当冒泡发生交换时,混乱度就加一。这样求得的混乱度貌似也与它这里定义的混乱度一样哎。而且我的方法不局限于字符串是DNA的那几个字母。

写了一次就AC了。然后发现同样的代码提交时一会儿时间是16ms,一会儿又是0ms,难道该题的测试用例还在不停的变化吗?

代码:

memory:248K, time16MS.

#include<iostream>

using namespace std;

int main(){
	int n,m;
	cin>>n>>m;
	char DNAs[100][51];
	char sortedDNAs[100][51];
	int sortedIndex[100][2];//两列,第一列代表DNA数组中的index值,第二列代表reverse次数
	int sortedIndexCount=-1;//sortedIndex数组最后一个元素的index
	for(int i=0;i<m;i++){
		cin>>DNAs[i];
		memcpy(sortedDNAs[i],DNAs[i],n*sizeof(char));
	}
	//冒泡排序 
	for(int num=0;num<m;num++){
		int count=0;
	    for(int i=0;i<n-1;i++){
	    	bool isReverse=false;
		    for(int j=0;j<n-i-1;j++){
			    if(sortedDNAs[num][j]>sortedDNAs[num][j+1]){
					char buffer=sortedDNAs[num][j];
					sortedDNAs[num][j]=sortedDNAs[num][j+1];
					sortedDNAs[num][j+1]=buffer;
					count++;
					isReverse=true;
				}
		    }
			if(isReverse==false)
				break;
	    }
		//插入排序,将混乱度由小到大排序
		int point=sortedIndexCount;
		while(point>=0&&sortedIndex[point][1]>count){
			sortedIndex[point+1][0]=sortedIndex[point][0];
			sortedIndex[point+1][1]=sortedIndex[point][1];
			point--;
		}
		point++;
		sortedIndex[point][1]=count;
		sortedIndex[point][0]=num;
		sortedIndexCount++;
	}
	for(int i=0;i<m;i++){
		cout<<DNAs[sortedIndex[i][0]]<<endl;
	}

	return 0;
}
这里用到了C++数组深拷贝的知识:

int a[10];
int b[10];
//想把b数组里的值拷贝到a数组里,使用
memcpy(a,b,10*sizeof(int))
另一个例子:

//使用memcpy复制
unsigned char R[3][2];
unsigned char Test[2] = {2,3};
memcpy(&R[i][0], &Test[0], sizeof(Test));


当然,我也要去看看别人是怎么写的啦~

原来大家不用冒泡,根据题目的定义来计算混乱度,传统写法是这样子的呀。时间也跟我差不多。

//Memory Time 
//252K   16MS 

#include<iostream>
#include<algorithm>
using namespace std;

typedef class dna
{
	public:
		int num;  //逆序数
		char sq[110];  //DNA序列
}DNAStr;

int InversionNumber(char* s,int len)
{
	int ans=0;  //s逆序数
	int A,C,G;  //各个字母出现次数,T是最大的,无需计算T出现次数
	A=C=G=0;
	for(int i=len-1;i>=0;i--)
	{
		switch(s[i])
		{
		    case 'A':A++;break;  //A是最小的,无逆序数
			case 'C':
				 {
					 C++;
					 ans+=A;  //当前C后面出现A的次数就是这个C的逆序数
					 break;
				 }
			case 'G':
				{
					G++;
					ans+=A;
					ans+=C;
					break;
				}
			case 'T':
				{
					ans+=A;
					ans+=C;
					ans+=G;
					break;
				}
		}
	}
	return ans;
}

int cmp(const void* a,const void* b)
{
	DNAStr* x=(DNAStr*)a;
	DNAStr* y=(DNAStr*)b;
	return (x->num)-(y->num);
}

int main(void)
{
	int n,m;
	while(cin>>n>>m)
	{
		DNAStr* DNA=new DNAStr[m];
		for(int i=0;i<m;i++)
		{
			cin>>DNA[i].sq;
			DNA[i].num = InversionNumber(DNA[i].sq,n);
		}
		qsort(DNA,m,sizeof(DNAStr),cmp);
		for(int j=0;j<m;j++)
			cout<<DNA[j].sq<<endl;
	}
	return 0;
}

另外,有一个解法,算法倒是一点不新奇,但是它使用了qsort。时间也跟我差不多。

#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
struct DNA{
  string s;     
  int value;
};
int cmp(const DNA *a, const DNA *b)  {   return (a->value-b->value);   }    
int main()
{
    int n,m;
    while(cin>> m >>n)
    {
         DNA *it=new DNA[n];      
         for(int i=0;i!=n;i++)
         {
            cin >> it[i].s;
            it[i].value = 0;
            for(int j=0;j!=m;j++)
                for(int k=j+1;k!=m;k++)
                     if(it[i].s[j]>it[i].s[k])   it[i].value++;
         }
         qsort(it,n,sizeof(DNA), (int (*)(const void *, const void *))cmp);
         for(int i=0;i!=n;i++)
              cout << it[i].s <<endl ;  
         delete[] it;             
    }
    return 0;    
}

它是用结构体包含其字符串和对应的inversions个数,从而用快排把inversions和其对应的字符串一次排出。

这里为了加强对快排函数qsort格式的认识和理解,从百度上转来了qsort对7种类型数据的快排格式和一个实例:

七种qsort排序方法

<本文中排序都是采用的从小到大排序>

一、对int类型数组排序
int num[100];

int cmp ( const void *a , const void *b ) { 
   return *(int *)a - *(int *)b; 
} 
qsort(num,100,sizeof(num[0]),cmp); 
二、对char类型数组排序(同int类型)
char word[100];
int cmp( const void *a , const void *b ) { 
   return *(char *)a - *(int *)b; 
} 
qsort(word,100,sizeof(word[0]),cmp); 
三、对double类型数组排序(特别要注意)
double in[100];
int cmp( const void *a , const void *b ) { 
   return *(double *)a > *(double *)b ? 1 : -1; 
} 
qsort(in,100,sizeof(in[0]),cmp); 
四、对结构体一级排序
struct In { 
   double data; 
   int other; 
}s[100] 
//按照data的值从小到大将结构体排序,关于结构体内的排序关键数据data的类型可以很多种,参考上面的例子写 
int cmp( const void *a ,const void *b) { 
   return (*(In *)a).data > (*(In *)b).data ? 1 : -1; 
} 
qsort(s,100,sizeof(s[0]),cmp); 
五、对结构体二级排序
struct In { 
   int x; 
   int y; 
}s[100]; 
//按照x从小到大排序,当x相等时按照y从大到小排序 
int cmp( const void *a , const void *b ) { 
   struct In *c = (In *)a; 
   struct In *d = (In *)b; 
   if(c->x != d->x) return c->x - d->x; 
   else return d->y - c->y; 
} 
qsort(s,100,sizeof(s[0]),cmp); 
六、对字符串进行排序
struct In { 
   int data; 
   char str[100]; 
}s[100]; 
//按照结构体中字符串str的字典顺序排序 
int cmp ( const void *a , const void *b ) { 
   return strcmp( (*(In *)a)->str , (*(In *)b)->str ); 
} 
qsort(s,100,sizeof(s[0]),cmp); 
七、计算几何中求凸包的cmp
int cmp(const void *a,const void *b){ //重点cmp函数,把除了1点外的所有点,旋转角度排序 
   struct point *c=(point *)a; 
   struct point *d=(point *)b; 
   if( calc(*c,*d,p[1]) < 0) return 1; 
   else if( !calc(*c,*d,p[1]) && dis(c->x,c->y,p[1].x,p[1].y) < dis(d->x,d->y,p[1].x,p[1].y)) //如果在一条直线上,则把远的放在前面 
   return 1; 
   else return -1; 
} 
PS:
其中的qsort函数包含在<stdlib.h>的头文件里,strcmp包含在<string.h>的头文件里


对浮点型快排实例:源程序, vc6通过的:

#include <stdio.h>
#include <stdlib.h>
int fcmp(const float*,const float*);
typedef int(*QSORT_UDF)(const void *,const void *);
int main(){
   float fArray[10] = {32.1,456.87,332.67,442.0,98.12,451.79,340.12,54.55,99.87,72.5};
   qsort(fArray,10,sizeof(float),(QSORT_UDF)fcmp);
   for(int i=0;i<10; i++)
      printf(" %3.2f ",fArray[i]);
   return 0;
}
int fcmp(const float *a,const float *b){
   if( *a > *b )
      return 1;
   else if(*a < *b )
      return -1;
   return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值