交换瓶子问题(暴力求解 + 图论解法)

交换瓶子问题

文章目录

前言

知道题目用暴力算法是可以过的,注意数据范围是1~10000,卡在一个微妙的地方,不免让人想用暴力算法,但是我们现在又不在赛场上,自然是多多益善,在这里还会介绍图论的解法,喜欢的小伙伴可以点个赞啦。

题目描述

有 N 个瓶子,编号 1∼N,放在架子上。

比如有 5 个瓶子:

2 1 3 5 4

要求每次拿起 2个瓶子,交换它们的位置。

经过若干次后,使得瓶子的序号为:

1 2 3 4 5

对于这么简单的情况,显然,至少需要交换 2 次就可以复位。

如果瓶子更多呢?你可以通过编程来解决。

输入格式

第一行包含一个整数 N,表示瓶子数量。

第二行包含 N 个整数,表示瓶子目前的排列状况。

输出格式

输出一个正整数,表示至少交换多少次,才能完成排序。

数据范围
1≤N≤10000,

输入样例1:

5

3 1 2 5 4

输出样例1:

3

输入样例2:

5

5 4 3 2 1

输出样例2:

2

暴力解法【能过】

类似于选择排序这样的,与当前位置不同的数直接在后面的数组当中找到符合的数与之交换,前面的数已经排好序了,不需要考虑

cpp 复制代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N =1e4+7;
int a[N];
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    int cnt=0;
    for(int i=1;i<=n;i++){
        if(a[i]!=i){
            for(int j=i+1;j<=n;j++){
                if(a[j]==i) swap(a[j],a[i]),cnt++;
            }        
        }
    }
    cout<<cnt;
}

图论解法

知识预备【交换环】

我们先举例分析:看下图

我们可以得到 3 个环

每个环是闭环,入度为 1 ,出度为 1。构建方式如上图所示

下面我们对环进行操作:

假设有个大环:

每次分解只能产生一个环
而我们最终的目的是将所有大环分解成一个一个小环,每个瓶子回到了本该属于自己3的位置,每次的分解操作只是一次交换

swap(a[ i ] , a [ j ])

现在我们有 n 个数, 假设产生 k 个环 ,那么我们至少需要 n - k 步操作才能使得大环变成一个一个最小环。而只要有环的长度>=2,那么我们就可以将其分解开来,使得可以在 n - k 步操作完成全部分解

现在我们只要求环的数量就行【类似于链表】 ,那么直接上代码

代码

解析都在代码注释当中呦

cpp 复制代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N =1e4 + 7;
bool st[N];//判断一个数是否有被纳入环内
int a[N];//存储原数组

int main(){
    int n;cin>>n;
    int ans=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    for(int i=1;i<=n;i++){
        if(!st[i]){//从 1 号位开始枚举
            ans++;
            for(int j=i;!st[j];j=a[j]){
                //这里j=a[j]是本来的数--》本来数的位置上 的 现在的数
                st[j]=true;
            }
        }
    }
    cout<<n-ans<<endl;
}

暴力做法和图论做法的对比

上面的是图论,下面的是暴力。

总结

这边博客介绍了 2 种思路,图论的做法比较新奇,上述的结论也适合在其他类型的题目当中求解,后续还会更新图论相关的内容,喜欢的小伙伴可以点个关注啦

相关推荐
罗湖老棍子2 小时前
Biorhythms(信息学奥赛一本通- P1639)
算法·数论·裴蜀定理·扩展欧几里得·扩展中国剩余定理
程序喵大人7 小时前
【C++入门】编译链接模型 - 01 一个 C++ 程序是怎样变成可执行文件的
开发语言·c++·编译链接模型
奋发向前wcx8 小时前
CSP-J复赛模拟赛4 王晨旭补题 2026.10.5
算法
by209999 小时前
vector 的模拟实现:扩容与边界的详细阐述(下)
c++·经验分享·vector·动态数组
念何架构之路10 小时前
zap采样器与性能优化内幕
算法·性能优化·哈希算法
晒太羊的猫11 小时前
hot100动态规划刷题
算法·动态规划
weixin_5310946912 小时前
heap_4内存管理
java·开发语言·算法
余额瞒着我当琳12 小时前
红黑树的实现--红黑树的概念、规则、效率、结构、旋转、查找、验证
数据结构·c++·算法
程序员南飞12 小时前
win系统安装minio
java·数据结构·算法
青少儿编程课堂12 小时前
AC自动机多模式串匹配精讲:校园关键词巡检实战解析
c++·python·算法·bfs·信息学竞赛