第七届蓝桥杯C/C++省赛B组 试题I:交换瓶子

有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;
}

在这里插入图片描述

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值