算法设计与分析: 5-1 子集和问题

本文探讨了如何利用回溯法解决子集和问题。给定一个包含正整数的集合S和目标和c,目标是找出S的一个子集,其元素之和等于c。文章提供了问题描述,并给出了基于Java的解决方案,包括数据输入和输出的说明。

5-1 子集和问题


问题描述

子集和问题的一个实例为S,t〈S,t〉。其中,S={x1x2...xn}S={x1,x2,...,xn}是一个正整数的集合,c是一个正整数。子集和问题判定是否存在 S 的一个子集 S1,使得 xS1x=c∑x∈S1x=c
试设计一个解子集和问题的回溯法。

对于给定的正整数的集合 S={x1x2...xn}S={x1,x2,...,xn}和正整数 c,编程计算 S 的一个子集S1,使得xS1x=c∑x∈S1x=c

数据输入:
第 1 行有 2 个正整数 n 和 c,n 表示 S 的大小,c是子集和的目标值。接下来的 1 行中,有 n 个正整数,表示集合 S 中的元素。


Java

package Chapter5HuiSuFa;

import java.util.Scanner;

public class ZiJiHe {

    private static int n,c,cw,r,bestw;
    private static int[] w,x,bestx;

    public static void main(String[] args){
        Scanner input = new Scanner(System.in);

        while (true){
            cw = 0;
            r = 0;
            bestw = 0;

            n = input.nextInt();
            c = input.nextInt();

            w = new int[n+1];
            x = new int[n+1];
            bestx = new int[n+1];

            for(int i=1; i<=n; i++){
                w[i] = input.nextInt();
                r += w[i];
            }

            if(backtrack(1))
                for(int i=1; i<=n; i++){
                    if(bestx[i] == 1)
                        System.out.print(w[i]+" ");
                }
            else
                System.out.println("No Solution!");
        }
    }

    private static boolean backtrack(int i){
        if(i > n){
            for(int j=1; j<=n; j++)
                bestx[j] = x[j];
            bestw = cw;
            if(bestw == c)
                return true;
            else
                return false;
        }

        r -= w[i];
        if(cw+w[i] <= c){
            x[i] = 1;
            cw += w[i];
            if(backtrack(i+1))
                return true;
            cw -= w[i];
        }
        if(cw+r > bestw){
            x[i] = 0;
            if(backtrack(i+1))
                return true;
        }
        r += w[i];
        return false;
    }
}

Input & Output

5 10
2 2 6 5 4
2 2 6 

Reference

王晓东《计算机算法设计与分析》(第3版)P179

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值