DFS优化——模拟赛化零题解

题目描述:

小林拥有 \(2\) 个集合,亮亮拥有 \(3\) 个集合,这五个集合大小相等,且集合中包
含的都是整数。现在他们两个要进行心算比赛。比赛的规则是,将这五个集合放在一起,谁能先从每个集合中各选一个数,使得选出的五个数之和为 \(0\),谁就获得胜利。由于这五个集合都不小,而小林和亮亮事先并不知道是否能存在这样的五个数,因此他们决定先把五个集合都交给你,由你来编程判断是否存在符合条件的五个数。

输入格式:

第一行一个整数 \(N\) ,表示集合的大小。 接下来五行每行 \(N\) 个整数,表示这五个集合内的元素。

输出格式:

如果能找到符合条件的五个数,则输出“YES”,否则输出“NO”。

数据范围:

\(a[i] \le 1e8, n \le 200\)

思路:

这个题目如果用爆搜并且在输出“YES”之后就退出,这样大概能够拿七十几分,如果要AC的话必须要对这个爆搜进行优化。首先我们可以预处理出第一个集合与第二个集合之间任意一对数的和,之后我们再预处理出第四个集合与第五个集合之间任意一对数的和。之后我们先枚举第一个集合与第二个集合之间任意一对数的和,之后我们再枚举第三个集合的数。然后我们相当于只要在四个集合与第五个集合之间任意一对数的和中找到一个数等于第三个的数的负数,如果找到就输出“YES”,并停止程序,要不然就一直找。这样时间复杂度就被降成了 \(O(N^3logN)\)

代码:

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

using namespace std;

const int N = 2e5 + 5;

int n;
int arr_tmp[10][N];
int arr[10][N];
int tail1 = 0, tail2 = 0;

int read() {
    int s = 0, w = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        s = s * 10 + ch - '0';
        ch = getchar();
    }
    return s * w;
}

int main(int argc, char const *argv[]) {
    //从文件输入输出
    freopen("zero.in", "r", stdin);
    freopen("zero.out", "w", stdout);

    n = read();
    for (register int i = 1; i <= 5; ++i) 
        for (register int j = 1; j <= n; ++j) 
            arr_tmp[i][j] = read();
    for (register int i = 1; i <= n; ++i) {
        for (register int j = 1; j <= n; ++j) {
            arr[1][++tail1] = arr_tmp[1][i] + arr_tmp[2][j];
            arr[2][++tail2] = arr_tmp[4][i] + arr_tmp[5][j];
        }
    }
    sort(arr[1] + 1, arr[1] + 1 + tail1);
    sort(arr[2] + 1, arr[2] + 1 + tail2);
    bool flag = false;
    for (register int i = 1; i <= n; ++i) {
        for (register int j = 1; j <= tail2; ++j) {
            int t = (-arr_tmp[3][i]) - arr[1][j];
            if (binary_search(arr[2] + 1, arr[2] + 1 + tail2, t)) {
                printf("YES\n"), flag = true;
                break;
            }
        }
        if (flag) break;
    }
    if (!flag) printf("NO\n");
    return 0;
}

转载于:https://www.cnblogs.com/lixiao189/p/9819823.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值