• 交换座位


    题目描述

    在一场集体婚礼上,有n对新人需要坐在连续排列的 2n个座位上合影,同一对新人彼此挨着。由于进场时各对新人并未按序入座,请计算最少交换座位的次数,以便使每对新人均可并肩坐在一起。一次交换可选择任意两人,让他们互换座位。
    全部新人的序号可用 0 到 2n-1 的整数表示,第一对是 (0, 1),第二对是 (2, 3),以此类推,最后一对是 (2n-2, 2n-1)。
    row[i]指最初坐在第 i 个座位上的新人编号,i是从0到(2n-1)的一个升序全排列,row不存在重复值。

    输入描述:

    输入共有2行,第一行为n,即共有多少对新人(2≤n≤100000 ),第二行为row,即2n个座位上的初始新人编号。
    输出描述:
    输出最少交换座位的次数。

    示例1

    输入

    2
    0 2 1 3
    输出
    1
    说明
    我们只需要交换1和2的位置即可

    示例2

    输入

    2
    3 2 0 1
    输出
    0
    说明
    无需交换座位,所有的新人都已经并肩坐在一起

    思路:

    1、为了找到所属的另一半,不能每次都进行遍历查找。因此,需要另一个数组arr[],存储每个人所在row[]中的位置。

    2、以row=[0,2,1,3]为例,0想要找到另一半1,先找到1所在的位置,为arr[1]=2。之后,0为了和1坐在一起,0抢占3的位置(为什么不是抢占2的位置呢)。没有座位的3,自然是又进行寻找另一半2的位置的过程。

    3、按照步骤2的方法,如果记录抢位置次数作为交换次数的话,会比实际交换次数多1。

    4、怎么结束步骤2的循环呢,0原本所在的row[0]的位置被抢占后,循环就结束。

    5、如果row=[0,2,1,3,4,6,5,7],只从0找的话,后面的4、6、5、7无法凑成一对,所以需要依次判断row[2i]和row[2i+1]是否是情侣,如果不是,则进行步骤2。

    6、最后代码如下:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    int minSwapsCouples(int n, vector<int>& row) {
    	int *a= new int[2 * n];//存储每个人所在row[]的位置
    	int len = n * 2;
    	for (int i = 0; i<len; i++)
    		a[row[i]] = i;
    	int sum = 0;//交换次数
    	int i = 0;
    	while (i<len)
    	{
    		if (row[i] / 2 == row[i + 1] / 2) { i += 2; continue; }//如果相邻座位是情侣,则继续
    		else//如果不是情侣
    		{
    			int n = row[i], m, c, index;//m是n要找的情侣,index为m的在row[]的位置
    			do
    			{
    				if (n % 2) m = n - 1;
    				else m = n + 1;
    				index = a[m];
    				if (index % 2) index--;
    				else index++;
    
    				c = row[index];//坐着的人走开
    				row[index] = n;//情侣坐成一对
    				n = c;//走开的人继续找另一半
    				sum++;
    			} while (index != i);//经过几次循环后,初始的位置被占领了,循环结束  
    			sum--;
    		}
    	}
    
    	return sum;
    }
    
    int main()
    {
    	int n = -1;
    	cin >> n;
    	vector<int> row;
    	for (int i = 0; i < 2 * n; i++)
    	{
    		int temp = -1;
    		cin >> temp;
    		row.push_back(temp);
    	}
    	int result = minSwapsCouples(n, row);
    	cout << result << endl;
    	return 0;
    }
    

    参考:https://blog.csdn.net/ZRXSLYG/article/details/80461203

  • 相关阅读:
    回溯算法
    回溯算法
    回溯算法
    回溯算法思想
    贪心算法
    C#多线程操作界面控件的解决方案
    jQuery教程
    html css JavaScript网页渲染
    jQuery与JavaScript与ajax三者的区别与联系
    asp.net MVC中form提交和控制器接受form提交过来的数据
  • 原文地址:https://www.cnblogs.com/whiteBear/p/12801436.html
Copyright © 2020-2023  润新知