例题8-3 UVA1152 4 Values whose Sum is 0(21行AC代码)

紫书刷题进行中,题解系列【GitHub|CSDN

例题8-3 UVA1152 4 Values whose Sum is 0(21行AC代码)

题目大意

给定4个长度为n个序列A,B,C,D,求四元组(a,b,c,d)的和为0所有可能组合,四个元素依次属于四个序列。

注意,当序列A中存在重复值时,依旧计数

思路分析

直接思路是用一个四重循环,枚举每个可能组合,必定超时,所以接着优化,观察等式a+b+c+d=0,可发现只要确定任意三个就可以得到第四个值,可将第四个序列排序,然后二分查找,可将复杂度降维O(logn*n^3),可依旧过高,需继续优化。

以上思路给了启发,用已知变量确定其余变量,用查找替代遍历,因此可计算出A和B所有组合的和,用map/哈希表存储,再枚举C和D的所有组合和scd,再map中查找是否存在-scd,若存在,即表明找到一个合法解。时间复杂度为O(logn*n^2)

本题算法思想叫做**中途相遇法**,从问题的两个方向来解决问题,最后汇集一点。
例如**双向bfs**,从两侧来加速解决问题的速度,就像挖隧道,两侧一块动手,工期减半,所以这种思想常常用来优化算法

举一反三

问题通式:a1^i1 op1 a2^i2 op2 ... op(n-1) an^in opn val
其中a1...an表示变量;i1...in表示次方数,0~n;op1...opn表示操作符(+-*/%...);val为指定的表达式值
实际上,任意表达式均可用类似方式优化分解,不过当数量过多时,分解处理较难
例子:
四平方和:a^2 + b^2 + c^2 + d^2 = val
四立方和,五立方和...

AC代码(C++11)

#include<bits/stdc++.h>
using namespace std;
const int maxn=4005;
int A[maxn], B[maxn], C[maxn], D[maxn], sumAB[maxn];
int main() {
    int T, n;
    scanf("%d", &T);
    for (int k=0; k < T; k ++) {
        if (k != 0) puts("");
        scanf("%d", &n);
        for (int i=0; i < n; i ++) scanf("%d %d %d %d", &A[i], &B[i], &C[i], &D[i]);
        unordered_map<int, int> mp;
        for (int i=0; i < n; i ++) // A+B
            for (int j=0; j < n; j ++) mp[A[i]+B[j]] ++; // 计算每个和出现次数
        int ans=0;
        for (int i=0; i < n; i ++) // C+D
            for (int j=0; j < n; j ++) ans += mp[-(C[i]+D[j])];
        printf("%d\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值