2022-6-3 最短区间,池塘数量,挑选数字,交友,加油站,染车

1. 最短区间 - 双指针

现在给定一个整数s以及一个长度为n的整数数列a[0],a[1],a[2],a[3]....a[n-1] (全为正数),

请你求出总和不小于s的连续子序列的长度的最小值。如果解不存在,则输出0

输入

第一行:两个整数,表示 s 与 n,其中1≤s≤10^9,1≤n≤500000;
第二行:n个用空格隔开的整数,表示 a[0] a[1] ... a[n-1],其中对于任意a[i]有1≤a[i]≤10^9。

输出

输出总和不小于s的连续子序列长度的最小值。
如果解不存在,则输出0。

输入样例

50 20
10 8 9 3 11 8 5 1 1 1 1 20 8 9 11 4 13 22 9 6

输出样例

4

Code

#include<bits/stdc++.h>

#define MAXN 500005
#pragma GCC optimize(2)
using namespace std;
using ull = unsigned long long;

ull arr[MAXN];


int main() {
    ios::sync_with_stdio(false);
    int s, n;
    cin >> s >> n;
    for (int i = 0; i < n; i++) cin >> arr[i];

    ull sum = 0;
    int i = 0, j = -1, minLength = INT_MAX;

    while (j++ < n) {
        while (sum >= s) {
            minLength = min(minLength, j - i);
            sum -= arr[i++];
        }
        sum += arr[j];
    }

    cout << (minLength == INT_MAX ? 0 : minLength);

    return 0;
}

2. 池塘数量 - DFS

最近大雨连连,积水把农夫约翰的农田里,很多地方都变成了水池。农夫约翰的池塘可以被表示为一个n行,每行有m个方格的矩形。每个方格要么是'W'要么是'.'。农夫约翰想要统计他的农田里有多少个池塘,一个池塘是指一个由'W'方格组成的极大连通块。这里认为两个方格相邻当且仅当他们在左上左下右上右下这八个方向中的某一个相邻。

给出农夫约翰的农田,帮他统计有多少个池塘。

输入

第一行两个正整数n和m 接下来n行,每行一个长为m的字符串表示这一行的农田
30%的数据: 1<=n,m<=20 60%的数据: 1<=n,m<=60 100%的数据: 1<=n,m<=300

输出

一行一个整数表示农夫约翰的农田中的池塘数量

输入样例

12 8
...W.WWW
WWW..W..
W.WW.WWW
..W..WWW
WW..WWWW
.WWW..W.
.W....WW
........
.WW.WW..
W.WWWW..
...W...W
...W..WW

输出样例

3

Code

#include<bits/stdc++.h>

#pragma GCC optimize(2)
using namespace std;

bool grid[305][305];
int n, m;
const vector<pair<int, int>> DIR = {{0,  1}, {0,  -1}, {1,  0}, {-1, 0},
                                    {1,  1}, {1,  -1}, {-1, 1}, {-1, -1}};

void dfs(int x, int y) {
    if (x < 0 || y < 0 || x >= n || y >= m || !grid[x][y]) return;
    grid[x][y] = false;
    for (auto&[dx, dy]:DIR) dfs(x + dx, y + dy);
}

int main() {
    ios::sync_with_stdio(false);

    cin >> n >> m;
    string s;
    for (int i = 0; i < n; i++) {
        cin >> s;
        for (int j = 0; j < m; j++) grid[i][j] = (s[j] == 'W');
    }

    int ans = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (grid[i][j]) {
                ans++;
                dfs(i, j);
            }
        }
    }

    cout << ans;

    return 0;
}

3. 挑选数字 - 回溯&剪枝

给出n个正整数,从中挑选若干个,使得他们的和为m。如果存在多个,输出排序后字典序最小的一组。如果没有找到任何一组,输出"No Solution"

输入

第一行:2个数n,m(1≤n≤30, 1≤m≤10^8)
第2-n+1行:每行1个数ai(1≤ai≤10^7)

对于50%的数据,1≤n≤20;
对于100%的数据,1≤n≤30, 1≤m≤10^8,1≤ai≤10^7。

输出

输出共1行,对应选中的数字,中间用空格分隔。如果没有找到任何一组,输出"No Solution"。

输入样例

5 15
1
3
5
7
9

输出样例

1 5 9

代码

#include<bits/stdc++.h>

#pragma GCC optimize(2)
using namespace std;
int n, m;
vector<int> path;

int arr[31], rsum[31];

bool backtracking(int iStart, int target) {
    if (target == 0) return true;
    for (int i = iStart; i < n; ++i) {
        if (target < arr[i] || target > rsum[i]) break;
        path.push_back(arr[i]);
        if (backtracking(i + 1, target - arr[i])) return true;
        path.pop_back();
    }
    return false;
}

int main() {
    ios::sync_with_stdio(false);

    cin >> n >> m;
    for (int i = 0; i < n; ++i) cin >> arr[i];

    sort(arr, arr + n);
    
    for (int i = n - 1; i >= 0; --i) rsum[i] = rsum[i + 1] + arr[i];

    if (backtracking(0, m)) {
        for (int i : path) cout << i << ' ';
    } else {
        cout << "No Solution";
    }

    return 0;
}

4. 交友 - BFS

一场舞会中有n个人(编号0到n−1),小A和小B也在其中(编号为0和1)。这n个人有一些是朋友关系,有一些不是。为了让小A和小B成为朋友,不如跳舞!我们认为当两个人有一个共同的朋友时,这两个人可以跳一支舞,并成为朋友。问最少要跳几场舞使得小A和小B成为朋友。数据保证a[i,j] = a[j,i]。

数据范围:1<=n<=100

输入

第一行一个整数n,表示舞会中的人数。 接下来为一个n*n的字符矩阵,其中第i行第j列(i,j都从0开始标号)的字母为'Y'当且仅当编号为i,j的两人是朋友,字母为'N'当且仅当编号为i,j的两人不是朋友。

输出

输出仅一行一个整数ans表示最少需要跳舞的场数,如果两人已经是朋友则输出0,如果两人无论如何也无法成为朋友,则输出-1。

输入样例

6
NNYYNN
NNNNYY
YNNNYN
YNNNNY
NYYNNN
NYNYNN

输出样例

2

代码

#include<bits/stdc++.h>

#pragma GCC optimize(2)
using namespace std;
int n;

bool graph[105][105];
bool visited[105];

int bfs() {
    queue<int> q;
    int dist = -1;
    q.push(0);
    while (!q.empty()) {
        int size = q.size();
        while (size--) {
            int next = q.front();
            visited[next] = true;
            q.pop();
            if (next == 1) return dist;
            for (int i = 0; i < n; i++) {
                if (graph[next][i] && !visited[i]) q.push(i);
            }
        }
        dist++;
    }
    return -1;
}

int main() {
    ios::sync_with_stdio(false);

    cin >> n;
    string s;
    for (int i = 0; i < n; i++) {
        cin >> s;
        for (int j = 0; j < n; j++) graph[i][j] = (s[j] == 'Y');
    }

    cout << bfs();

    return 0;
}

5. 加油站 - 贪心

一辆卡车,初始时距离终点L,油量为P,在起点到终点途中有n个加油站,每个加油站油量有限,而卡车的油箱容量无限,卡车在行车途中,每走一个单位的距离消耗一个单位的油量,给定n个加油站距离起点的距离A[i]以及油存储量B[i]。问卡车是否能到达终点,如果可达,最少需要加多少次油,否则输出-1。输入不保证有序。

1<=n<=10000; 1<=L<=1000000; 1<=P<=10000001<=A[i]<L1<=B[i]<=100

输入

第一行三个数L,P,n,以空格隔开,分别表示起点到终点的距离、现在的油量、中途加油站数; 之后n行,每行两个数A[i]和B[i],以空格隔开,表示该加油站到起点的距离和油存储量。

输出

输出一个数,表示最少的加油次数。

输入样例

100 15 2
15 75
90 25

输出样例

2

代码

#include<iostream>
#include<queue>
#include<algorithm>

#define MAXN 10005
#pragma GCC optimize(2)
using namespace std;
int L, P, n;
pair<int, int> A[MAXN];

int solve() {
    priority_queue<int> pue;
    for (int i = 0; i <= n; i++) {
        while (A[i].first > P) {
            if (pue.empty()) return -1;
            P += pue.top();
            pue.pop();
        }
        pue.push(A[i].second);
    }
    return n + 1 - pue.size();
}

int main() {
    ios::sync_with_stdio(false);

    cin >> L >> P >> n;
    for (int i = 0; i < n; ++i) cin >> A[i].first >> A[i].second;
    A[n] = {L, 0};  // 视终点为加油站
    sort(A, A + n + 1, [](const pair<int, int> &lo, const pair<int, int> &hi) {
        return lo.first < hi.first;
    });
    cout << solve();

    return 0;
}

6. 染车 - DFS

n×m的棋盘上某些位置放着几个车,两个车互相攻击当且仅当如下条件全部满足:

1、两车同行或同列;2、两车之间没有其他车;3、两车颜色不同。

现在给你这些车的位置,请你用尽量多的颜色给它们染色,使得任意两辆车都不互相攻击。

数据范围:1<=n, m<=20

输入

读入第一行包含两个整数n, m,表示棋盘的行数和列数
接下来n行m列,描述整个棋盘。棋盘中共包含两类字符,字符.表示空地,字符R表示车。
对于42.5%的数据,1≤n,m≤5;
对于87.5%的数据,1≤n,m≤10;
对于100%的数据,1≤n,m≤20;

输出

输出共一行,表示你能保证车不互相攻击的前提下,能用的最多的颜色数。

输入样例

3 4
.R.R
R.R.
.R.R

输出样例

2

代码

#include<bits/stdc++.h>

#pragma GCC optimize(2)
using namespace std;

bool graph[20][20];
int n, m, ans = 0;

void dfs(int x, int y) {
    graph[x][y] = false;
    for (int i = 0; i < n; ++i) {
        if (graph[i][y]) dfs(i, y);
    }
    for (int j = 0; j < m; ++j) {
        if (graph[x][j]) dfs(x, j);
    }
}

int main() {
    ios::sync_with_stdio(false);

    string s;
    cin >> n >> m;
    for (int i = 0; i < n; ++i) {
        cin >> s;
        for (int j = 0; j < m; ++j) graph[i][j] = (s[j] == 'R');
    }

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            if (graph[i][j]) {
                ans++;
                dfs(i, j);
            }
        }
    }

    cout << ans;

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值