您的位置:首页 > 其它

紫书第八章-----高效算法设计(归并排序求逆序对数)

2018-02-09 00:54 477 查看

Brainman POJ - 1804

【代码一(暴力)】

#include<iostream>

using namespace std;

const int maxn=1000+5;

int a[maxn],t[maxn];
long long cnt;
int T,N,kase=0;

void solve(){
cnt=0;
for(int i=0;i<N;i++){
for(int j=i+1;j<N;j++){
if(a[i]>a[j]) cnt++;
}
}
}

int main()
{
cin>>T;
while(T--){
cin>>N;
for(int i=0;i<N;i++)
cin>>a[i];
solve();
cout<<"Scenario #"<<++kase<<":"<<endl<<cnt<<endl<<endl;
}
return 0;
}


【代码二(归并排序求逆序对数)】

/*
该程序参考刘汝佳《算法竞赛入门经典》(第2版)
本代码是用归并排序来统计逆序对数。
首先归并排序的分治法的三步走战略:划分问题+递归求解+合并问题
其次,归并排序统计逆序对数目的原理是这样子的:首先我们得明确
一个事实,比如6 1 7 2这四个数,6 1这两个数放一块,7 2两个数放
一块,这两个部分内部不论怎么交换,并不影响由于其他块的数产生
的逆序对数目,现在以6 1 7 2为例,我们以7 2这一块来说,归并排序
中当7进入临时空间的时候,看看6 1这一块还剩下几个元素没有入临时
空间,剩下的元素必定比7大,剩下的元素个数就是由于7产生的逆序对
数目,同样地1产生的逆序对数目类似统计,同样,由于不同块之间互不
影响,递归解决此问题。说的有点乱,但仔细想想是这个道理!!!!!
*/

#include<iostream>

using namespace std;

const int maxn=1000+5;

int a[maxn],t[maxn];
int cnt;

//归并排序求解逆序对数目,左闭右开区间
void merge_sort(int a[],int x,int y,int t[]){
if(y-x>1){  //递归结束条件
int mid=x+(y-x)/2;  //分治第一步:划分问题,尽量等分为两份
int p=x,q=mid,i=x;
merge_sort(a,x,mid,t);//分治第二步:递归左边求解
merge_sort(a,mid,y,t);//分治第二步:递归右边求解
while(p<mid || q<y){
if(q>=y || (p<mid && a[p]<=a[q])) t[i++]=a[p++];    //复制给临时辅助数组空间
else{
t[i++]=a[q++];  //复制给临时辅助数组空间
cnt=cnt+mid-p;  //统计逆序对数目
}
}
for(i=x;i<y;i++) a[i]=t[i]; //分治第三步:合并问题
}
}

int main()
{
int T,N,kase=0;
cin>>T;
while(T--){
cin>>N;
for(int i=0;i<N;i++)
cin>>a[i];
cnt=0;
merge_sort(a,0,N,t);
cout<<"Scenario #"<<++kase<<":"<<endl<<cnt<<endl<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: