首页 > 试题广场 >

数组分组

[编程题]数组分组
  • 热度指数:128786 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
\hspace{15pt}对于给定的 n 个整数 a_1, a_2, \dots, a_n,将其分为 a,b 两个数组,满足:
\hspace{23pt}\bullet\,所有 5 的倍数元素均在 a 数组中;
\hspace{23pt}\bullet\,所有 3 的倍数元素(不包括 5 的倍数)均在 b 数组中;
\hspace{23pt}\bullet\,其他元素可以任意分配。
\hspace{15pt}求解是否存在一种分配方案,使得 a 数组中各个元素之和等于 b 数组中各个元素之和。每一个元素要么在 a 数组中,要么在 b 数组中;数组可以为空,此时和为 0。如果存在这样的方案,输出 \rm true,否则输出 \rm false

输入描述:
\hspace{15pt}第一行输入一个整数 n \left(1 \leqq n \leqq 30\right) 代表给定的整数个数。
\hspace{15pt}第二行输入 n 个整数 a_1, a_2, \dots, a_n \left(-500 \leqq a_i \leqq 500\right)
\hspace{15pt}保证数据随机生成。


输出描述:
\hspace{15pt}如果存在满足条件的分配方案,输出 \rm true,否则输出 \rm false
示例1

输入

4
1 5 -5 1

输出

true

说明

\hspace{15pt}在这个样例中,a 数组可以为 \{5, -5, 1\}b 数组可以为 \{1\},满足条件。
示例2

输入

3
3 5 8

输出

false
本题在计算上是可以简化的,不过示例的运算量都不大,所以这点简化也无所谓了。

import sys
n=int(input())
n_list=list(map(int,input().split()))
a,b,c=[],[],[]
for num in n_list:
    if num%3==0 and num%5!=0:
        b.append(num)
    elif num%5==0:
        a.append(num)
    else:
        c.append(num)
diff=abs(sum(a)-sum(b))
target=(sum(c)-diff)//2
if (sum(c)-diff)%2!=0&nbs***bsp;(target!=0 and c==[]):
    print("false")
    sys.exit()
if target in c&nbs***bsp;(target==0 and c==[]):
    print("true")
    sys.exit()
#穷举子集再分别求和。运算量会大一些
'''result=[[]]
for num in c:
    result+=[curr+[num] for curr in result]
for num in result:
    if sum(num)==target:
        print("true")
        sys.exit()
print("false")'''
#不穷举子集,直接穷举子集之和。如果想要更快点可以加个判断条件提前终止循环
import copy
flag=[False]*(max(abs(target),abs(min(c)))+max(target,abs(max(c)))+1)
flag[0]=True
for num in c:
    flag_temp=copy.deepcopy(flag)#列表、字典必须用这种“深拷贝”
    for i in range(max(target,max(c)),min(target,min(c))-1,-1):
        flag_temp[i]=flag[i]&nbs***bsp;flag[i-num if i-num<=max(target,max(c)) else i]
    flag=flag_temp
print("true" if flag[target] else "false")


发表于 2025-12-16 18:21:37 回复(0)
import itertools
n = int(input())
A = list(map(int, input().split()))
a = []
b = []
rest = []
for i in A:
    if i % 5 == 0:
        a.append(i)
    else:
        if i % 3 == 0:
            b.append(i)
        else:
            rest.append(i)
if rest == []:
    if sum(a) == sum(b):
        print('true')
    else:
        print('false')
else:
    for i in range(1, int(len(rest)/2)+2):
        for combin in itertools.combinations(rest, i):
            if sum(a)+sum(list(combin)) == sum(b)+sum(rest)-sum(list(combin))&nbs***bsp;sum(b)+sum(list(combin)) == sum(a)+sum(rest)-sum(list(combin)):
                print('true')
                exit()
    print('false')

发表于 2025-10-10 17:12:33 回复(0)
def dfs(five,three,other):
    if not other:
        if sum(five) == sum(three):
            return True
        else:
            return False
    else:
        return dfs(five+other[:1],three,other[1:])&nbs***bsp;dfs(five,three+other[:1],other[1:])

n = int(input())
s = list(map(int,input().split()))
a,b,temp = [],[],[]
for i in s:
    if i % 5 == 0:
        a.append(i)
    elif i % 3 == 0:
        b.append(i)
    else:
        temp.append(i)
print('true' if dfs(a,b,temp) else 'false')

发表于 2025-08-05 21:23:54 回复(0)
num = int(input())
arr5 = []
arr3 =[]
arrqita=[]
arr = list(map(int ,input().split()))

def f(arrqita,cha):
    if  len(arrqita) == 0 :# 不到最后不知道结果啊
        if  cha ==0:
            return True
        else:
            return False
    else:
        return f(arrqita[1:],arrqita[0] +cha) or f(arrqita[1:],cha -arrqita[0] )

   

for i in arr:
    if i % 5 == 0 :
        arr5.append(i)
    elif i % 3 ==0:
        arr3.append(i)
    else:
        arrqita.append(i)
arr5_sum= sum(arr5)
arr3_sum= sum(arr3)
cha =arr5_sum - arr3_sum
# print(len(arrqita),cha)
if f(arrqita,cha):
    print("true")
else:
    print('false')
递归最重要的是搞清楚终止条件
发表于 2025-05-06 03:10:34 回复(0)
好像评论没有用动态规划的,我来
a = input()
b = input().strip().split(" ")
all_list = [int(x) for x in b]
# all_list = [-2,2]

a_list = []
b_list = []
maybe_list = []
for num in all_list:
    if num % 5 == 0:
        a_list.append(num)
    elif num % 3 == 0:
        b_list.append(num)
    else:
        maybe_list.append(num)
maybe_list.sort()
N = sum(all_list) / 2 - sum(a_list)
# 所以maybe_list需要尝试求和为N
# print(N)

def dp(i, j):
    # maybe的前i+1(i为下标,从0开始)个数是否可以求和为j
    if i < 0:
        if len(maybe_list) == 0 and j == 0:
            return True
        return False
    if j == 0:
        return True
    for item in maybe_list[: i + 1]:
        if item == j:
            return True
    return dp(i - 1, j) or dp(i - 1, j - maybe_list[i])

if dp(len(maybe_list) - 1, N):
    print("true")
else:
    print("false")


发表于 2024-12-04 20:07:35 回复(0)
def findx(x, nums):
    if x == 0:
        return True
    if x in nums:
        return True
    for index, j in enumerate(nums):
        target = x - j
        list1 = nums[:]
        list1.pop(index)
        if findx(target, list1):
            return True
    return False

n = int(input())
nums = list(map(int, input().split()))
list_5 = []
list_3 = []
list_others = []
for j in nums:
    if j % 5 ==0:
        list_5.append(j)
        continue
    if j % 3 == 0:
        list_3.append(j)
        continue
    list_others.append(j)
target = abs(sum(list_5) - sum(list_3))
sumothers = sum(list_others)
target2 = sumothers - target
if target2 % 2 != 0 :
    print('false')
else:
    target2 = target2/2
    if findx(target2, list_others):
        print('true')
    else:
        print('false')
发表于 2024-08-13 14:43:24 回复(0)
import sys
from itertools import combinations

while True:
    try:
        n = input()
        x = list(map(int,input().split()))
        a3 =[0] + [i for i in x if i%3==0 and i%5!=0]
        a5 = [0] + [i for i in x if i%5==0]
        a0 = [0] + [i for i in x if i not in a3+a5]
        k = 'false'
        # print(a3,a5,a0,sep = '\n')
        for i in range(1,len(a0)+1):
            if k=='true':
                break
                    
            for j in combinations(a0,i):
                if (sum(a3)+sum(a0)-sum(a5))%2==0 and sum(j) == (sum(a3)+sum(a0)-sum(a5))//2:
                    k = 'true'
                    # print(j,sum(j),(sum(a3)+sum(a0)-sum(a5)))
                    break
        print(k)
 
    except:
        break




发表于 2024-06-13 16:08:34 回复(0)
简单数学推导:问题实质是一个”部分和问题“
将原数组先分为5整除组、3整除组以及剩余组,要将剩余组的元素分配到前两个组
设三个组现有元素和分别为:a、b、c
则假设可分时,两个组最终的元素和应该都是(a+b+c)/2
说明c要分成两份,每份分别为:(c+a-b)/2,(c-a+b)/2
因为全是整数,所以上式应该满足整除,否则不可分
如果能整除,问题转换为:在一个数组中,是否存在一个子集的和等于给出的目标值?
这个问题就是”部分和问题“,是一个经典的NP完全问题。没有已知的多项式时间复杂度的解决方案。
所以在数据量不大时,穷举所有子集合,判断子集合的和是否等于目标值不是不可。
以下是该问题的一个穷举算法:
import itertools


def arr_grouping(arr):
    # 分组:能被5整除、能被3整除、其余的元素
    five_multiple = [x for x in arr if x % 5 == 0]
    three_multiple = [x for x in arr if x % 3 == 0 and x not in five_multiple]
    arr_surplus = [x for x in arr if x not in five_multiple and x not in three_multiple]

    # 总和计算
    sum_five = sum(five_multiple)
    sum_three = sum(three_multiple)

    # 尝试将 arr_surplus 组合成与剩余元素相等的总和
    total_sum = sum(arr_surplus)
    target_sum = (total_sum + sum_five - sum_three) / 2

    # 如果目标和不是整数,表示不能均分
    if target_sum != int(target_sum):
        return False

    target_sum = int(target_sum)

    # 检查 arr_surplus 的组合是否能达到 target_sum
    for k in range(len(arr_surplus) + 1):
        # 使用组合来检测目标和
        for comb in itertools.combinations(arr_surplus, k):
            if sum(comb) == target_sum:  # sum([]) = 0
                return True
    return False


# 输入读取
n = int(input())
arr = [int(x) for x in input().split()]

# 输出结果
print(str(arr_grouping(arr)).lower())

发表于 2024-05-05 18:34:10 回复(0)
def fun(sum_3, sum_5, nums_other):
    if len(nums_other) == 0:
        if sum_3 == sum_5:
            return True
        else:
            return False
    else:
        fun1 = fun(sum_3 + nums_other[0], sum_5, nums_other[1::])
        fun2 = fun(sum_3, sum_5 + nums_other[0], nums_other[1::])
        return fun1 or fun2


n = int(input())
nums = list(map(int, input().split()))
nums_5 = []
nums_3 = []
nums_other = []
for i in nums:
    if i % 5 == 0:
        nums_5.append(i)
    elif i % 3 == 0:
        nums_3.append(i)
    else:
        nums_other.append(i)
sum_3 = sum(nums_3[::])
sum_5 = sum(nums_5[::])

print('true') if fun(sum_3, sum_5, nums_other) else print('false')
编辑于 2024-03-18 21:08:07 回复(0)
是否存在的解的问题 感觉深度优先,平均效率会好点,但是对长一点的数组内存可能会溢出。
import sys

# 广度优先
def BFS(fiveL: list, threeL: list, otherL: list):
    # 递归结束条件
    if not otherL:
        if sum(fiveL) == sum(threeL):
            return 1
        else:
            return 0
    res1 = BFS(fiveL + otherL[:1], threeL, otherL[1:])
    res2 = BFS(fiveL, threeL + otherL[:1], otherL[1:])
    return res1 + res2


# 深度优先
def DFS(fiveL: list, threeL: list, otherL: list, cIndex: int = 0, pathR: list = []):
    if pathR == []:
        pathR = [0 for i in range(len(otherL))]
    # 结果判定
    if cIndex == len(otherL):
        if sum(fiveL) == sum(threeL):
            return True
    # 递归至所有数分配完毕
    if cIndex < len(otherL):
        if pathR[cIndex] == 0:
            pathR[cIndex] += 1
            if DFS(fiveL + [otherL[cIndex]], threeL, otherL, cIndex + 1, pathR):
                return True
        elif pathR[cIndex] == 1:
            pathR[cIndex] += 1
            if DFS(fiveL, threeL + [otherL[cIndex]], otherL, cIndex + 1, pathR):
                return True
    else:
        # 回溯至有未走路线的节点
        cIndex -= 1
        if pathR[cIndex] == 1:
            fiveL.pop()
        if pathR[cIndex] == 2:
            threeL.pop()
        while pathR[cIndex] >= 2:
            if cIndex == 0:
                return
            pathR[cIndex] = 0
            cIndex -= 1
            if pathR[cIndex] == 1:
                fiveL.pop()
            if pathR[cIndex] == 2:
                threeL.pop()
        if DFS(fiveL, threeL, otherL, cIndex, pathR):
            return True


n = int(input())
numStr = input()
numStr = numStr.replace("\n", "")
numList = list(map(int, numStr.split()))

aList = []  # a组 5的倍数
bList = []  # b组 3(非5)的倍数
cList = []  # c组 待分组
for i in numList:
    if i % 5 == 0:
        aList.append(i)
    elif i % 3 == 0:
        bList.append(i)
    else:
        cList.append(i)

# 广度优先
# res = BFS(aList, bList, cList)
# if res>0:
#    print("true")
# else:
#    print("false")
# print(res)
# 深度优先
res = DFS(aList, bList, cList)
if res:
    print("true")
else:
    print("false")


发表于 2024-02-16 23:03:22 回复(1)
def add(a5,a3,a0):#看别人代码写的
    if len(a0) == 0:
        if a5 == a3:
            return True
        else:
            return False
    else:
        return add(a5+a0[0],a3,a0[1:])&nbs***bsp;add(a5,a3+a0[0],a0[1:])

while 1:
    try:
        n = int(input())
        m = list(map(int,input().split()))
        a = [[],[],[]]
        for i in m:
            if i%5 == 0:
                a[0].append(i)
            elif i%3 == 0:
                a[1].append(i)
            else:
                a[2].append(i)
        a5,a3 = 0,0
        for i in a[0]:
            a5 += i
        for i in a[1]:
            a3 += i
        print(str(add(a5,a3,a[2])).lower())

    except:
        break

发表于 2024-01-03 16:52:33 回复(0)
n, nums = input(), list(map(int, input().split()))
res = [0]
for i in nums[:]:
    if i % 5 == 0:
        res[0] += i
        nums.remove(i)
    elif i % 3 == 0:
        res[0] -= i
        nums.remove(i)

for i in nums:
    new_res = []
    for e in res:
        new_res.extend([e + i, e - i])
    res = list(set(new_res))
print('true' if 0 in res else 'false')

发表于 2023-05-05 22:01:35 回复(1)
n = int(input())
s = list(map(int, input().split()))

# a存5的倍数 包括15
a = list()
# b存3的倍数 不包括15 <- 用 elif 实现
b = list()
# c存其他的数
c = list()

for i in range(len(s)):
    if s[i] % 5 == 0:
        a.append(s[i])
    elif s[i] % 3 == 0:
        b.append(s[i])
    else:
        c.append(s[i])
# sum求和
a = sum(a)
b = sum(b)

# 递归一下 
# 虽说条件写的是 k == len(c) 
# 但是其实k=0的时候,第一轮儿计算的时候 abc的值并没有改变
# 第二轮儿的时候 dfs(a+c[k],b,c,k+1)&nbs***bsp; dfs(a,b+c[k],c,k+1) 才改变
# 所以停止条件是 k == len(c) 正好把所有的c里面的值都计算了 a == b时 return True
def dfs(a,b,c,k):
    if k == len(c) and a == b:
        return True 
    if k == len(c) and a != b:
        return False
    res = dfs(a+c[k],b,c,k+1)&nbs***bsp; dfs(a,b+c[k],c,k+1)
    return res  

if dfs(a,b,c,0):
    print('true')
else:
    print('false')

发表于 2022-11-18 20:00:29 回复(0)

递归非常简单直观

n = input()
nums = list(map(int, list(input().split())))
def group(three, five, others):
    if len(others) == 0:
        if sum(three) == sum(five):
            return True
        else:
            return False
    return group(three+[others[0]], five, others[1:]) or group(three, five+[others[0]], others[1:])

three, five, others = [], [], []
for num in nums:
    if num % 3 == 0:
        three.append(num)
    elif num % 5 == 0:
        five.append(num)
    else:
        others.append(num)
if group(three, five, others):
    print('true')
else:
    print('false')
发表于 2022-09-29 17:57:43 回复(0)
用combination
from itertools import combinations


a = input()
nums = list(map(int,input().split()))
que1 = []
que2 = []
que3 = []
for i in nums:
    if i % 5 == 0:
        que1.append(i)
    elif i%3 == 0:
        que2.append(i)
    else:
        que3.append(i)
if not que3:
    if sum(que1) == sum(que2):
        print('true')
    else:
        print('false')
else:
    flag = 'false'
    sum3 = sum(que3)
    for i in range(len(que3)+1):
        if flag == 'true':
            break
        for j in combinations(que3,i):
            if sum(que1)+2*sum(j) == sum(que2)+sum3:
                flag = 'true'
                break
    print(flag)
    


发表于 2022-09-25 19:57:12 回复(0)