题目:
Description
Input
Output
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; }
#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类型)
int cmp( const void *a , const void *b ) { return *(char *)a - *(int *)b; } qsort(word,100,sizeof(word[0]),cmp);三、对double类型数组排序(特别要注意)
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:
对浮点型快排实例:源程序, 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; }