首页 > 试题广场 >

数组分组

[编程题]数组分组
  • 热度指数:125237 时间限制: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 50\right) 代表给定的整数个数。
\hspace{15pt}第二行输入 n 个整数 a_1, a_2, \dots, a_n \left(-500 \leqq a_i \leqq 500\right)


输出描述:
\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
这道题用递归真是精彩,参考排在前几楼的大神的。
之前都不知道return 可以对 | | 这个运算符有效
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<strstream>
using namespace std;

bool f(int sum1,int sum2,int *p,int len,int i)
{
    if(i==len&&sum1==sum2)
        return true;
    if(i==len&&sum1!=sum2)
        return false;
    if(i<len)
    {
        return f(sum1+(*(p+i)),sum2,p,len,i+1)||f(sum1,sum2+(*(p+i)),p,len,i+1);
    }
}
int main()
{
    int n;
    while(cin>>n)
    {
        int b[10000]= {0};
        int a[10000]= {0};
        int sum1=0,sum2=0;
        int p=0;
        for(int i=0; i<n; i++)
        {
            cin>>b[i];
            if(b[i]%5==0)
                sum1+=b[i];
            else if(b[i]%3==0)
                sum1+=b[i];
            else
            {
                a[p++]=b[i];
            }
        }
        int len=p;
        int i=0;
        bool iscan=f(sum1,sum2,a,len,0);
        if(iscan)
            cout<<"true"<<endl;
        else
            cout<<"false"<<endl;
    }
    return 0;
}


发表于 2019-10-12 18:04:58 回复(1)
#include<stdio.h>
int main()
{
    int num;
    while(scanf("%d",&num)!=EOF)
    {
        int a[100];
        int i;
        for(i=0;i<num;i++)
        {
            scanf("%d",&a[i]);
        }
        int sum1=0;
        int sum2=0;
        int sum=0;
        for(i=0;i<num;i++)
        {
            if(a[i]>0&&a[i]%5==0)
                sum1+=a[i];
            else if(a[i]>0&&a[i]%3==0)
                sum2+=a[i];
            else
                sum+=abs(a[i]);
        }
        if(sum>abs(sum1-sum2)&&(sum-abs(sum1-sum2))%2==0)
            printf("true\n");
        else
            printf("false\n");
    }
    return 0;
}

发表于 2020-11-27 22:46:54 回复(1)
#include<iostream>
#include<vector>
using namespace std;
//判断nums[index....len]放入fivesum和threesum中能否有组合使fivesum==threesum
bool isExists(int fivesum, int threesum, int index, vector<int>nums){
    if (index == nums.size()){
        if (fivesum == threesum){
            return true;
        }
        else{
            return false;
        }
    }
    return isExists(fivesum + nums[index], threesum, index + 1, nums) || isExists(fivesum, threesum + nums[index], index + 1, nums);
}
int main(){
    int n;
    while (cin >> n){
        vector<int>nums;
        int a;
        int fivesum = 0;
        int threesum = 0;
        for (int i = 0; i < n; i++){
            cin >> a;
            if (a % 5 == 0){//5的倍数放入fivesum
                fivesum += a;
            }
            else if (a % 3 == 0){//3的倍数放入threesum
                threesum += a;
            }
            else{//其他数放入nums中待分配
                nums.push_back(a);
            }
        }
        if (isExists(fivesum, threesum, 0, nums)){
            cout << "true" << endl;
        }
        else{
            cout << "false" << endl;
        }
    }
    return 0;
}

发表于 2019-07-21 19:23:43 回复(2)
我认为重点是:按绝对值排序,想了好久
发表于 2017-04-05 22:35:06 回复(1)
Rust 题解,一个坑:不能用原数组的引用,必须用克隆。
fn main() {
    let mut n = String::new();
    let mut nums = String::new();
    std::io::stdin().read_line(&mut n);
    std::io::stdin().read_line(&mut nums);

    let mut sum3 = 0;
    let mut sum5 = 0;
    let mut others = vec![];

    nums.trim()
        .split(" ")
        .map(|n| n.parse::<i32>().unwrap())
        .for_each(|n| {
            if n % 5 == 0 {
                sum5 += n;
            } else if n % 3 == 0 {
                sum3 += n;
            } else {
                others.push(n);
            }
        });

    println!("{}", backtrack(others, sum3, sum5));
}

fn backtrack(mut nums: Vec<i32>, sum1: i32, sum2: i32) -> bool {
    match nums.pop() {
        Some(x) => {
            backtrack(nums.clone(), sum1 + x, sum2) || backtrack(nums.clone(), sum1, sum2 + x)
        }
        None => sum1 == sum2,
    }
}


发表于 2022-08-22 23:33:31 回复(0)
import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        List<Integer> a = new ArrayList<>(n);
        List<Integer> b = new ArrayList<>(n);
        List<Integer> c = new ArrayList<>(n);
        long sa = 0l;
        long sum = 0l;
        for (int i = 0; i < n; i++) {
            int j = sc.nextInt();
            if (j % 5 == 0) {
                a.add(j);
                sa += j;
            } else if (j % 3 == 0) {
                b.add(j);
                sum += j;
            } else {
                c.add(j);
                sum += j;
            }
        }
        sum += sa;
        if (Math.abs(sum % 2) == 1) {
            System.out.println(false);
            return;
        }
        long d = sum / 2 - sa;
        if (dfs(c, d, 0)) {
            System.out.println(true);
        } else {
            System.out.println(false);
        }
    }

    static boolean dfs(List<Integer> a, long m, int i) {
        if (i == a.size()) {
            return m == 0;
        }
        if (dfs(a, m, i + 1)) {
            return true;
        }
        if (dfs(a, m - a.get(i), i + 1)) {
            return true;
        }
        return false;
    }


}

发表于 2022-07-06 01:00:47 回复(0)
import java.util.*;
public class Main {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        List<Integer> group_3 = new ArrayList<>();
        List<Integer> group_5 = new ArrayList<>();
        List<Integer> group_free = new ArrayList<>();


        int count = sc.nextInt();
        while (count > 0) {
            int num = sc.nextInt();
            if (num % 5 == 0) {
                group_5.add(num);
            } else if (num % 3 == 0) {
                group_3.add(num);
            } else {
                group_free.add(num);
            }
            count--;
        }

        int sum_3 = 0, sum_5=0;
        for (int i : group_3) {
            sum_3 += i;
        }

        for (int i : group_5) {
            sum_5 += i;
        }


        System.out.println(process(group_free, 0, sum_3, sum_5));;

    }

    private static boolean process(List<Integer> free, int index, int sum_3, int sum_5) {

        if (index == free.size()) {
            if (sum_3 == sum_5) {
                return true;
            } else {
                return false;
            }
        }

        boolean giveTo3 = process(free, index + 1, sum_3 + free.get(index), sum_5);
        boolean giveTo5 = process(free, index + 1, sum_3, sum_5 + free.get(index));

        return giveTo3 || giveTo5;
    }

}

发表于 2022-06-06 23:48:48 回复(0)
//常规递归思路
import java.util.*;
public class Main {
    //flag可进行后续减枝操作
    public static boolean flag;
    public static void main(String[] args) {
        Scanner sc =new Scanner(System.in);
        while (sc.hasNext()) {
            int n = sc.nextInt();
            int[] nums = new int[n];
            for (int i = 0; i < n; i++) {
                nums[i] = sc.nextInt();
            }
            flag = false;
            recur(nums, 0, 0, 0);
            System.out.println(flag);
        }
    }
    public static void recur(int[] nums, int idx, int sum5, int sum3) {
        if (idx == nums.length) {
            if (sum5 == sum3) {
                flag = true;
            } 
            return;
        }
        if (nums[idx] % 5 == 0) {
            recur(nums, idx + 1, sum5 + nums[idx], sum3);
        } else if (nums[idx] % 3 == 0 && nums[idx] % 5 != 0) {
            recur(nums, idx + 1, sum5, sum3 + nums[idx]);   
        } else {
            recur(nums, idx + 1, sum5 + nums[idx], sum3);
            recur(nums, idx + 1, sum5, sum3 + nums[idx]);            
        }       
    }
}

发表于 2022-03-02 10:52:43 回复(0)
记数组的和为sum,显然只有sum为偶数时才有可能分解成两个和相等的子数组。先将5的倍数进行求和为sum1,3的倍数且非5的倍数求和为sum2,然后判断剩下的数能否凑出sum1就可以了(子集和问题)。
然后用递归来求解子集和问题,每层递归只考虑是否选择头部的元素进行求和,然后对当前数组切片nums[1:]进行下一层递归,只要这两种方式中有一种能够凑出指定和就行。
def judge(nums, target):
    n = len(nums)
    if n == 1 and nums[0] == target:
        return True
    elif n > 1:
        # 选择第一个数和不选第一个数两种情况
        return judge(nums[1:], target - nums[0])&nbs***bsp;judge(nums[1:], target)
    return False

while True:
    try:
        n = int(input())
        arr = list(map(int, input().strip().split()))
        total = sum(arr)
        if total % 2 == 1:
            print("false")
        else:
            target = total // 2     # 两组数的目标和
            group3, group5, other = 0, 0, []
            for num in arr:
                if num % 5 == 0:
                    group5 += num   # 5的倍数进行求和
                elif num % 3 == 0 and num % 5 != 0:
                    group3 += num   # 不包括5的倍数的3的倍数进行求和
                else:
                    other.append(num)
            # 检查other中的数能不能凑出和为target-group3以及和为target-group5的两部分
            print("true" if judge(other, target - group3) else "false")
    except:
        break

编辑于 2021-04-02 15:52:28 回复(0)
牛客网的判卷系统真的有病,本地可以执行,自测可以执行。但是就是print('true')输出不了,在print('true')语句前后加上print('123')都可以输出,就是这句话输出不了,这道题真是日了牛客网了
def findm(n, m):
    if m < 1&nbs***bsp;len(n) < 1:
        return
    elif m in n:
        return True
    if findm(n[:-1], m):
        return True
    elif findm(n[:-1], m - n[-1]):
        return True
    else:
        return False
def pf(f):
    if f:
        print('true')
    else:
        print('false')
try:
    n = int(input())
    m = list(map(int, input().split()))
    li3 = []
    li5 = []
    res = []
    for i in range(len(m)):
        if m[i] % 5 == 0:
            li5.append(m[i])
        elif m[i] % 3 == 0:
            li3.append(m[i])
        else:
            res.append(m[i])
    sumall = sum(m)
    if sumall % 2:
        print('false')
    else:
        M = int(sumall / 2 - sum(li5))
        pf(findm(res,M))
        #if findm(res, M):
except Exception as e:
    print(e)

发表于 2020-09-03 17:07:20 回复(1)
前几名的答案不对啊。
反例 :
14
3 3 3 3 3 3 3 3 3 3 5 5 11 89
发表于 2020-07-14 11:54:05 回复(0)
#include "stdio.h"
#include "math.h"
#include <stdbool.h>

bool func(int i, int a[], int n, int ret, int sum)
{
    if(i == n)
        return abs(ret) == abs(sum);

    return func(i+1, a, n, ret+a[i], sum) || func(i+1, a, n, ret-a[i], sum);
}

int main()
{
    int n;

    while(scanf("%d", &n) != EOF) {
        int i, j = 0, a[n], sum3=0, sum5=0, other[n];

        for(i=0; i<n; i++) {
            scanf("%d", &a[i]);
            if(a[i]%3 == 0) {
                sum3 += a[i];
            } else if(a[i]%5 == 0) {
                sum5 += a[i];
            } else
                other[j++] = a[i];
        }

        int sum = abs(sum3-sum5);
        if(func(0, other, j, 0, sum) == true)
            puts("true");
        else
            puts("false");
    }
}

编辑于 2020-07-05 16:08:01 回复(0)
#include <iostream>
#include <vector>
using namespace std;

bool istrue(int sum1, int sum2, vector<int> list, int index)
{
    if(index==list.size() && sum1!=sum2) return false;
    if(index==list.size() && sum1==sum2) return true;
    if(index!=list.size())
        return(istrue(sum1+list[index], sum2, list, index+1) || istrue(sum1, sum2+list[index], list, index+1) ); 
}


int main()
{
    int num;
    while(cin>>num)
    {
        vector<int> list;
        int sum1=0,sum2=0;
        for(int i=0;i<num;i++){
            int tmp;
            cin>>tmp;
            if(tmp%5==0)
                sum1+=tmp;
            else if(tmp%3==0)
                sum2+=tmp;
            else
                list.push_back(tmp);
        }
        
        bool flag = istrue(sum1,sum2,list,0);
        if(flag==1) cout<<"true"<<endl;
        else cout<<"false"<<endl;
    }
}
发表于 2020-06-16 12:47:09 回复(0)
#~万物皆可递归~
#include <stdbool.h>
bool s;
void checkGetin(int num[],int numt[],int numf[],int m,int k,int kt,int kf){
    if (m==k) {
        int count1=0,count2=0;
        for (int i=0; i<kt; i++)
            count1+=numt[i];
        for (int i=0; i<kf; i++)
            count2+=numf[i];
        if (count1==count2)
            s=true;
        return;
    }
    numt[kt++]=num[m++];
    checkGetin(num, numt, numf, m, k, kt, kf);
    kt--; m--;
    numf[kf++]=num[m++];
    checkGetin(num, numt, numf, m, k, kt, kf);
}

int main(){
    void checkGetin(int [],int [],int [],int ,int ,int ,int );
    int n;
    while (~scanf("%d",&n)) {
        int num[1000],numt[500],numf[500];
        int k=0,kt=0,kf=0;
        for (int i=0; i<n; i++) {
            int temp;
            scanf("%d",&temp);
            if (temp%3==0)
                numt[kt++]=temp;
            else if (temp%5==0)
                numf[kf++]=temp;
            else
                num[k++]=temp;
        }
        s=false;
        checkGetin(num, numt, numf, 0, k, kt, kf);
        if (s)
            printf("true\n");
        else
            printf("false\n");
    }
    return 0;;
}

发表于 2020-05-26 11:17:19 回复(0)
就只有我一个人觉得题目和测试用例给的有问题吗,题目说了将两组中各元素加起来的和相等,就是最简单的加法运算,和减法,取绝对值有什么关系,1,5,-5,1.怎么分配才能让分成的两组数组加起来和一样呢
发表于 2020-03-20 08:39:51 回复(0)
输入数组来判断能否根据要求的条件分成和相等的两组,是否可以先将输入的数组求和然后看是否是2的整倍数,如果是,说明有可能能分成值相等的两组,并将整除2后的值记为M,M的值就应该是能分成两组后每组的和,然后再进行数据分组,分别计算5倍数组和3倍数租数据的和相对于M的差值,在剩下没有分组的数据寻找能够匹配的分别加入到两个数组,有匹配就是TRUE,没有就是FALSE。如果不能,直接就是FALSE了。求大神解答这种思路是否可以呢?
发表于 2019-11-08 10:55:26 回复(0)
#include <bits/stdc++.h>

using namespace std;

bool dfs(vector<int> &cnt, vector<bool> &book, int res)
{
    if (res == 0) return true;
    for (int i = 0; i < cnt.size(); i++)
    {
        if (!book[i])
        {
            book[i] = true;
            if(dfs(cnt, book, res - cnt[i])) return true;
            book[i] = false;
        }

    }
    return false;
}


int main()
{
    int n;
    while (cin >> n)
    {
        vector<int> num;
        vector<int> cnt;
        bool flag=true;
        int nu;
        for (int i = 0; i<n; i++)
        {
            cin >> nu;
            num.push_back(nu);
            
        }
        int sum1 = 0;
        int sum2 = 0;
        int sum3 = 0;
        for (int i = 0; i<num.size(); i++)
        {
            if ((num[i] % 3) == 0) sum1 += num[i];
            else if ((num[i] % 5) == 0) sum2 += num[i];
            else
            {
                cnt.push_back(num[i]);
                sum3 += num[i];
            }
        }
        int len = cnt.size();
        
        int m = abs(sum1 - sum2);
        if ((sum3 - m) % 2 != 0)
        {
            flag = false;
        }
        else
        {
            vector<bool> book(len, false);
            int sss = (sum3 - m) / 2;
            flag = dfs(cnt, book, sss);
        }
        if(flag) cout << "true"<< endl;
        else cout<<"false"<<endl;
    }
    
    
    system("pause");
    return 0;
}  

发表于 2018-08-05 22:47:15 回复(0)
求解思路:
1.扫描所有输入整数,得到所有5的倍数的连加和sum5,所有三的倍数的连加和sum3,其他正数放在整数数组qita[ ],其个数q_n;
2.考虑到数组qita[ ]的每个元素都可以加给sum5或sum3,共有2的q_n种情况,遍历所有情况求解
3.遍历时考虑   将一个q_n位二进制数与数组其qita[ ]中的q_n个元素对应,区分其分到5数组还是3数组,即加到sum5上还是sum3上。
#include <stdio.h>
#include <math.h>
int main(void){
int n=0;
while(scanf("%d",&n)!=EOF){
int sum5=0;
int sum3=0;
int qita[100];
int n_q=0;
int tr=0;
while(n--){
int num_now;
scanf("%d",&num_now);
if(num_now%5==0){
sum5+=num_now;
}
else if(num_now%3==0){
sum3+=num_now;
}
else{
qita[n_q]=num_now;
n_q++;
}
}

int t=1;
int ll=0;
while(ll<n_q){
t=t*2;
ll++;
}
while(t){

int k=t-1;
int l=n_q;
int sum55=sum5;
int sum33=sum3;
while(l){

if(k%2){
sum55+=qita[l-1];
}
else{
sum33+=qita[l-1];
}
k=k/2;
l--;
}

if(sum55==sum33){
printf("true\n");
tr=1;
break;
}

t--;
}


if(!tr){
printf("false\n");
}

}

return 0;
}
编辑于 2017-08-25 22:22:51 回复(0)
这个题目有点难啊
也是百度了相关知识点之后才整理出的一个答案
核心问题就是如何在一个集合中找到和为定值的子集(NP问题)
递归回溯

我的答案(另附一个会超时的穷举式解法):
#include <iostream>
#include <vector>
#include <numeric>

using namespace std;

// 子集树递归
bool subset(vector<int> restVector, int startIndex, int endIndex, int leftSum, int rightSum)
{
    // 左边和为0(即不用找)
    if (0 == leftSum)
    {
        return true;
    }

    // 剩余元素只有1个
    if (startIndex == endIndex)
    {
        return (restVector[startIndex] == leftSum)
               || (restVector[startIndex] == rightSum);
    }

    // 排除最后一个元素
    int newLeftSum = leftSum - restVector[endIndex];
    int newRightSum = rightSum - restVector[endIndex];

    if ((leftSum != rightSum) && (leftSum != newLeftSum))
    {
        return (subset(restVector, startIndex, endIndex - 1, leftSum, rightSum)
                || subset(restVector, startIndex, endIndex - 1, newLeftSum, newRightSum));
    }
    else
    {
        if (leftSum != rightSum)
        {
            return subset(restVector, startIndex, endIndex - 1, leftSum, rightSum);
        }
        else
        {
            return subset(restVector, startIndex, endIndex - 1, leftSum, newLeftSum);
        }
    }
}

int main()
{
    int N;
    while (cin >> N)
    {
        // 初始化时将原数组分成三个部分
        // 含有5的倍数的集合+含有3的倍数的集合+剩余的
        // 并分别求和
        vector<int> fiveVector;
        vector<int> threeVector;
        vector<int> restVector;
        int fiveSum = 0;
        int threeSum = 0;
        int restSum = 0;

        int tempValue;
        for (int i = 0; i < N; ++i)
        {
            cin >> tempValue;
            if (tempValue % 5 == 0)
            {
                fiveVector.push_back(tempValue);
                fiveSum += tempValue;
            }
            else if (tempValue % 3 == 0)
            {
                threeVector.push_back(tempValue);
                threeSum += tempValue;
            }
            else
            {
                restVector.push_back(tempValue);
                restSum += tempValue;
            }
        }

        // 根据和差原理求得含有5的集合的剩余部分的和
        // 联立这两个方程:x5 + x3 = restSum && x5 - x3 = threeSum - fiveSum
        // 即可解得x5 = (restSum + threeSum - fiveSum) / 2;
        // 由于是整数 要确保整除
        if ((restSum + threeSum - fiveSum) % 2 == 0)
        {
            int fiveRestSum = (restSum + threeSum - fiveSum) / 2;

            // 如果有剩余元素
            if (restVector.size() > 0)
            {
                bool finalFlag = subset(restVector, 0, int(restVector.size() - 1), fiveRestSum, fiveRestSum);

                if (finalFlag)
                    cout << "true" << endl;
                else
                    cout << "false" << endl;
            }
            else
            {
                // 如果没有剩余元素
                if (fiveRestSum == 0)
                {
                    cout << "true" << endl;
                }
                else
                {
                    cout << "false" << endl;
                }
            }
        }
        else
        {
            cout << "false" << endl;
        }
    }

    return 0;
}


下面是一个会超时的一般穷举式解法:

#include <iostream>
#include <vector>
#include <numeric>

using namespace std;

// 标记位数组加1操作 1表示选中集合中的值
// 例如0111->1000
void FlagShift(vector<int> &flags)
{
    int carry = 0;  // 进位
    int index = (int)flags.size() - 1;

    if (flags[index] == 0)
    {
        flags[index] = 1;
    }
    else
    {
        while (flags[index] == 1)
        {
            flags[index] = 0;
            carry = 1;
            --index;
        }
        if (index >= 0)
        {
            flags[index] = carry;
        }
    }
}

int main()
{
    int N;
    while (cin >> N)
    {
        // 初始化时将原数组分成三个部分
        // 含有5的倍数的集合+含有3的倍数的集合+剩余的
        // 并分别求和
        vector<int> fiveVector;
        vector<int> threeVector;
        vector<int> restVector;
        int fiveSum = 0;
        int threeSum = 0;
        int restSum = 0;

        int tempValue;
        for (int i = 0; i < N; ++i)
        {
            cin >> tempValue;
            if (tempValue % 5 == 0)
            {
                fiveVector.push_back(tempValue);
                fiveSum += tempValue;
            }
            else if (tempValue % 3 == 0)
            {
                threeVector.push_back(tempValue);
                threeSum += tempValue;
            }
            else
            {
                restVector.push_back(tempValue);
                restSum += tempValue;
            }
        }

        // 根据和差原理求得含有5的集合的剩余部分的和
        // 联立这两个方程:x5 + x3 = restSum && x5 - x3 = threeSum - fiveSum
        // 即可解得x5 = (restSum + threeSum - fiveSum) / 2;
        // 由于是整数 要确保整除
        if ((restSum + threeSum - fiveSum) % 2 == 0)
        {
            int fiveRestSum = (restSum + threeSum - fiveSum) / 2;

            // 标记位01数组,用来表示剩下的元素的选中与否
            vector<int> flags(restVector.size(), 0);
            int thisFindSum;
            bool finalFlag = false;

            // 循环结束的条件为所有位为1  即标记位向量所有元素之和=剩余所有元素的数目
            while (accumulate(flags.begin(), flags.end(), 0) <= int(restVector.size()))
            {
                thisFindSum = 0;
                for (int i = 0; i < flags.size(); ++i)
                {
                    if (flags[i] == 1)
                    {
                        thisFindSum += restVector[i];
                    }
                }

                // 如果剩下所有元素中的某个子集和为需要的剩余部分和 则返回true
                if (thisFindSum == fiveRestSum)
                {
                    finalFlag = true;
                    break;
                }

                FlagShift(flags);
            }

            if (finalFlag)
                cout << "true" << endl;
            else
                cout << "false" << endl;
        }
        else
        {
            cout << "false" << endl;
        }
    }

    return 0;
}


发表于 2016-08-17 18:18:11 回复(0)

人生苦短解法

排行里那种两边分配的方法是不对的
这里好多分析太罗嗦,简洁一下

本题最终转换为:判断在一个整型数组中,是否存在和为某定值的组合

数组:除去被3、5整除之外的数列表
定值:(abs(sum3 - sum5) + sum_ls) / 2

代码:

def fun(ls, target, s=0):
    """
    递归方法判断整型数组 ls 中,是否存在和为 target 的组合,s 表示当前组合的和
    """
    found = False
    for i in range(len(ls)):
        if s + ls[i] == target:
            found = True
            break
        else:
            # 分为取当前值和不取当前值两种情况
            return fun(ls[i + 1:], target,  s + ls[i]) or fun(ls[i + 1:], target, s)
    return found

while True:
    try:
        #个数,数组,3的倍数和,5的倍数和,其它数和,其他数列表
        n, nums, sum3, sum5, sum_ls, ls = int(input()), [int(_) for _ in input().split()], 0, 0, 0, []

        for i in nums:
            if i % 5 == 0:
                sum5 += i
            elif i % 3 == 0:
                sum3 += i
            else:
                ls.append(i)

        #要单独判断 ls 为空的情况
        if len(ls) == 0:
            print('true') if sum3 == sum5 else print('false')
        else:
            sum_ls = sum(ls)

            #本题实际转换为判断 ls 中是否存在和为 target 的组合的问题。target 有小数显然不存在。
            if (abs(sum3 - sum5) + sum_ls) % 2 != 0:
                print('false')
            else:
                target = (abs(sum3 - sum5) + sum_ls) // 2
                print('true') if fun(ls, target) else print('false')
    except:
        break
发表于 2021-08-14 14:55:42 回复(1)