【题解】CF28B pSort

时间:2021-08-10
本文章向大家介绍【题解】CF28B pSort,主要包括【题解】CF28B pSort使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

第一道完全自己想+做出来的一道绿题!!!!!!心情大好( ,写篇题解记录一下qwq


接下来进入正题。

涉及的知识点:并查集

思路:

  • 一些数组,变量的定义:
     表示 位置 $i$ 的祖先。(注意这里说的是“位置”)
    $dis_i$ 表示可以移动的距离,也就是题目中的 $d$ 数组。
    $goal1_i$ 表示目标数列。

  • 如何判断位置为 $i$ 的数可不可以移动到 $j$ 位置上:如果这两个位置的祖先相同就可以。也就是说 $f_i$ 和 $f_j$ 的祖先相同就可以。
    find(j) == find(i) <— 这个就是判断祖先相同的代码

  • 什么时候,怎么将两个位置合并:如果位置 i 可以移动到位置 j 上(用 dis 数组判断),就将 $f_i$ 和 $f_j$ 合并。(注意考虑出界问题
    这一部分的代码↓

        int x,y;
        x = i+dis[i];
        y = i-dis[i];

        if(x <= n){
            f[find(x)] = find(i);
        }
        if(y >= 1){
            f[find(y)] = find(i);
        }

好了,思路差不多了,接下来就放一下代码qwq

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;

int n;
int goal1[10009];//目标序列
int dis[10009];
int f[100009];//f[i] 表示位置 i 的祖先 

void init(){
    for(int i=0; i<1000; i++)f[i] = i;
}

int find(int k){//路径压缩
    if(f[k] == k)return k;
    return f[k] = find(f[k]);
}
int main(){

    init();//初始化 

    cin >> n;
    for(int i=1; i<=n; i++){
        cin >> goal1[i];
    }
    for(int i=1; i<=n; i++){
        cin >> dis[i];
        int x,y;
        x = i+dis[i];
        y = i-dis[i];

        if(x <= n){//不出界再合并
            f[find(x)] = find(i);
        }
        if(y >= 1){//不出界再合并
            f[find(y)] = find(i);
        }

    }

    for(int i=1; i<=n; i++){
        int j = goal1[i];
        if(find(j) != find(i)){
            cout << "NO";
            return 0;//只要有一个不行(移动不到目标位置)就输出 "NO"
        }
    }   

   //成功运行到了最后,说明初始数列所有位置上的数都可以移动到目标位置,那就输出 "YES"
    cout << "YES";
    return 0;
} 

(自我感觉马蜂应该不错qwq 可读性比较高qwq)

最后,如果有什么问题欢迎指出!

原文地址:https://www.cnblogs.com/Jiayn/p/15123323.html