有N个瓶子,编号 1 ~ N,放在架子上。
比如有5个瓶子:
2 1 3 5 4
要求每次拿起2个瓶子,交换它们的位置。
经过若干次后,使得瓶子的序号为:
1 2 3 4 5
对于这么简单的情况,显然,至少需要交换2次就可以复位。
如果瓶子更多呢?你可以通过编程来解决。
输入格式为两行:
第一行: 一个正整数N(N<10000), 表示瓶子的数目
第二行:N个正整数,用空格分开,表示瓶子目前的排列情况。
输出数据为一行一个正整数,表示至少交换多少次,才能完成排序。
例如,输入:
5
3 1 2 5 4
程序应该输出:
3
再例如,输入:
5
5 4 3 2 1
程序应该输出:
2
分析:
从位置1枚举到N,如果编号不对,那么就与对应位置的瓶子交换。
贪心
#include<iostream>
#include<stdio.h>
using namespace std;
int a[10005];//a[i]表示位置i的瓶子编号
int b[10005];//b[i]表示i号瓶子的位置。没有这个数组的话,需要在a数组中循环找到i号瓶子(O(n)),用这个数组的话是O(1)
int main(){
int N;
int i;
int id;
int sum;
//设瓶子1为位置i的瓶子,瓶子2为i号瓶子
int id1,id2; //瓶子1的编号,瓶子2的编号
int pos1,pos2;//瓶子1的位置,瓶子2的位置
while(~scanf("%d",&N)){
for(i=1;i<=N;++i){
scanf("%d",&id);
a[i]=id;//位置i放id号瓶子
b[id]=i;//id号瓶子放到位置i
}
sum=0;
for(i=1;i<=N;++i){//位置从1遍历到N
if(a[i]==i)continue;//位置i放的是i号瓶子
//否则,瓶子2与瓶子1交换
id1=a[i];
pos1=i;
id2=i;
pos2=b[i];//没有b数组的话,需要在a数组中找到i号瓶子
++sum;
//瓶子1放到瓶子2的位置
a[pos2]=id1;//瓶子2的位置(pos2)放瓶子1(id1)
b[id1]=pos2;//瓶子1(id1)放到瓶子2的位置(pos2)
//瓶子2放到瓶子1的位置
a[pos1]=id2;//瓶子1的位置放瓶子2
b[id2]=pos1;//瓶子2放到瓶子1的位置
}
printf("%d\n",sum);
}
return 0;
}
选择排序
#include<iostream>
#include<stdio.h>
using namespace std;
int sum;
void SelectSort(int R[],int n){
int i,j,k;
int tmp;
for(i=0;i<n-1;++i){//做第i趟排序
k=i;
for(j=i+1;j<n;++j){//在当前无序区R[i..n-1]中选最小的R[k]
if(R[j]<R[k])k=j;//k记下目前找到的最小关键字所在的位置
}
if(k!=i){//交换R[i]和R[k]
tmp=R[i];
R[i]=R[k];
R[k]=tmp;
++sum;
}
}
}
int main(){
int N;
int a[10005];
int i;
while(~scanf("%d",&N)){
for(i=0;i<N;++i){
scanf("%d",&a[i]);
}
sum=0;
SelectSort(a,N);
printf("%d\n",sum);
}
return 0;
}