ACM-Subset sum

题目描述: Subset Sum
Tags: 回溯
子集和问题的一个实例为〈 S,t 〉。其中,S={x1 ,x2 ,…, xn }是一个正整数的集合,c是一个正整数。子集和问题判定是否存在S的一个子集S1,使得x1+x2+...+xk=S, 其中x1,x2...xk属于集合S1。 对于给定的正整数的集合S和正整数c,编程计算S 的一个子集S1,使得x1+x2+...+xk=S, 其中x1,x2...xk属于集合S1。
输入
第1 行有2 个正整数n 和c,n 表示S 的大小,c是子集和的目标值。接下来的1 行中,有n 个正整数,表示集合S 中的元素。
输出
子集和问题的解。当问题无解时,输出“No Solution!”。
样例输入
5 10
2 2 6 5 4
样例输出
2 2 6


思路:DFS,找一个子集树就可以了,但是总是PE。。。。。这个就很头痛。。。。。

 1 // subset sum.cpp : 定义控制台应用程序的入口点。
 2 //
 3 
 4 #include "stdafx.h"
 5 
 6 #include <iostream>
 7 #include <cstring>
 8 #include <cstdio>
 9 using namespace std;
10 
11 const int MAX = 1000;
12 int n, c, sign, arr[MAX], vis[MAX], sum[MAX];
13 
14 void print()
15 {
16     for (int i = 0; i<n; i++)    
17         if (vis[i]) cout << arr[i] << " ";        
18     cout << endl;
19 }
20 
21 
22 
23 //搜索的位置,目前的和
24 void DFS(int pos, int cur)
25 {
26     //cout << "pos:" << pos << "\tcur:" << cur << endl;
27     if (sign) return; //找到一组就可以直接结束搜索过程
28     if (cur == c)
29     {
30         sign = 1;  print();
31         return;
32     }
33 
34     //加个特殊判断,cur+余下<c 不可能凑够c
35     if (pos >= n || cur > c || cur + sum[n-1] - sum[pos-1] < c ) return;
36     
37 
38     vis[pos] = 1;//选择
39     DFS(pos + 1, cur + arr[pos]);
40 
41     vis[pos] = 0;//不选择
42     DFS(pos + 1, cur);
43 
44 }
45 
46 
47 int main()
48 {
49     while (cin >> n >> c)
50     {
51         sign = 0;
52         memset(vis, 0, sizeof(vis));
53         memset(sum, 0, sizeof(sum));
54 
55         for (int i = 0; i < n; i++)
56         {
57             cin >> arr[i];
58             sum[i] = sum[i-1] + arr[i]; //减枝!!判断剩下的所有的数字是否能够合成c
59         }
60         if (sum[n-1] < c)//很重要的剪枝!!如果所有的数加起来都小于c,那么不可能有解。。之前有三组TLE,加了这一步竟然给蒙过了。。
61         {
62             //cout << "sum[n - 1]:"<<sum[n - 1] << endl;
63             cout << "No Solution!";            
64         }
65         else
66         {
67             DFS(0, 0);
68             if (sign == 0) cout << "No Solution!"<<endl;
69         }
70 
71         
72     }
73 
74     return 0;
75 }

 




转载于:https://www.cnblogs.com/x739400043/p/8505373.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值