第六讲---双指针、BFS与图论(上课)

1.双指针

在这里插入图片描述

1.1日志统计

在这里插入图片描述
在这里插入图片描述
暴力
在这里插入图片描述
双指针
在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;
#define x first
#define y second

typedef pair<int, int> PII;


const int N = 100010;


int n,d,k;
PII logs[N]; //记录
int cnt[N]; //所有id出现的次数
bool st[N]; //判断每一个帖子是否在热帖

int main()
{
    scanf("%d%d%d",&n,&d,&k);
    for(int i = 0;i < n;i++)    scanf("%d%d",&logs[i].x,&logs[i].y);
    
    sort(logs,logs + n);
    
    for(int i = 0,j = 0;i < n;i++)
    {
        int id = logs[i].y;
        cnt[id]++;
        
        while(logs[i].x - logs[j].x >= d)
        {
            cnt[logs[j].y]--;
            j++;
        }
        if(cnt[id] >= k)    st[id] = true;
            
    }
    
    for(int i = 0;i < N;i++)
        if(st[i])   printf("%d\n",i);
        
    return 0;
}

2.BFS

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

2.1献给阿尔吉侬的花束

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>

#define x first
#define y second

using namespace std;

const int N = 210;

typedef pair<int, int> PII;

int n, m;
char g[N][N];
int dist[N][N];  // 把判重和距离数组合为一个

int bfs(PII start, PII end)  // 注意 start end都是PII类型的 别写错了
{
    queue<PII> q;

    memset(dist, -1, sizeof dist);  // 把距离数组都初始化成-1

    dist[start.x][start.y] = 0;  // 起点开始,距离为0

    q.push(start);  // 起点 入队

    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

    while(q.size())
    {
        PII t = q.front();

        // 弹出队头
        q.pop();

        for (int i = 0; i < 4; i ++ )
        {
            int a = t.x + dx[i], b = t.y + dy[i]; 

            if (a < 0 || a >= n || b < 0 || b >= m) continue;  // 出界,跳出本次循环
            if (dist[a][b] != -1) continue;    // 走过了,跳出本次循环
            if (g[a][b] == '#') continue;    // 撞到障碍物

            dist[a][b] = dist[t.x][t.y] + 1;

            if (end == make_pair(a, b)) return dist[a][b];  // 走到终点了,返回距离

            q.push({a, b});
        }

    }

    return -1;
}

int main()
{
    int T;
    cin >> T;

    while(T --)
    {

        scanf("%d%d", &n, &m);

        for (int i = 0; i < n; i ++ ) scanf("%s", g[i]);

        PII start, end;
        for (int i = 0; i < n; i ++ )
            for (int j = 0; j < m; j ++ )
                if (g[i][j] == 'S') start = {i, j};
                else if (g[i][j] == 'E') end = {i, j};

        int distance = bfs(start, end);

        if (distance == -1) printf("oop!\n");
        else printf("%d\n", distance);

    }

    return 0;


}

注:make_pair(x,y)可以返回一个pair

make_pair(x,y)	

3.图论

3.1交换瓶子

在这里插入图片描述

在这里插入图片描述
暴力
1、通过观察可以发现,我们每一个数都必须回到它自己的位置上,比如 1 必须在第一位,2 必须在第二位上

2、那么我们就可以这样操作,由于每个数必须回到自己的位置,直接从 1 枚举到 n,如果当前位置的数不等于它的下标,那么我们就必须要把它给替换掉

3、设当前位置为 i 的话,那么我们就从 i+1 开始往后枚举,直到找到对应的 a[j] 和我们的 i 相等,那么我们就把上个数交换,把交换次数++

4、容易证明这个算法的正确性,由于每个数必须回到原来的位置,所以我们这样子操作不会出现多于的步骤,因为每次操作都是必须的,即使这个算法看起来很麻烦

#include<bits/stdc++.h>
using namespace std;
const int N=10010;
int a[N],n,t;
int ans=0;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    for(int i=1;i<=n;i++)
    {
        if(a[i]!=i)
        {
            for(int j=i+1;j<=n;j++)
            {
                if(a[j]==i)
                {
                    t=a[i];
                    a[i]=a[j];
                    a[j]=t;
                }
            }
            ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
} 

置换群算法
在这里插入图片描述

在这里插入图片描述

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 10010;

int n;
int b[N];
bool st[N];//判重数组

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &b[i]);

    int cnt = 0;
    //找环,统计环的数量
    for (int i = 1; i <= n; i ++ )
        if (!st[i])//当前这个点未被找到
        {
            cnt ++ ;
            for (int j = i; !st[j]; j = b[j])//这个点可以到的所有点
                st[j] = true;
        }

    printf("%d\n", n - cnt);

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Next---YOLO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值