1. 程式人生 > >ACM-Subset sum

ACM-Subset sum

cpp 找到 namespace clu .cpp pos esp 直接 nbsp

題目描述: 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 }




ACM-Subset sum