子集和问题 - 回溯&搜索

 

题目地址:http://www.51cpc.com/web/problem.php?id=4264

 

  其实一看到这道题我就想到了01背包,但是卡死在了如何顺序输出;

  个人人为回溯本身就会用到搜索,像是充分不必要条件的那种感觉。

  试了下动规的方法,并不适用于此题,动规可以得到是否有解或求出其中一组解,但无法按输入顺序输出第一组解。

 

Summarize:

  1. 注意特判所有元素加起来都小于C;

  2. 递归内循环从0开始,由于vis不必担心重复;但题目要求顺序输出,故应从0开始; 

 

 

附AC代码:

 1 #include<iostream>
 2 #include<cstring>
 3 #define inf 1e9
 4 typedef long long LL;
 5 using namespace std;
 6  
 7 const int N = 7e3+5;
 8 LL n,c;
 9 LL a[N], vis[N], can;
10  
11 void dfs(int i, LL sum)
12 {
13     if(can || i>=n) return;
14     
15     if(sum == c)
16     {
17         can=1;
18         int i=0;
19         while(!vis[i] && i<n) i++;
20         cout<<a[i];
21         for(i++; i<n; i++)
22             if(vis[i]) cout<<' '<<a[i];
23         cout<<endl;
24         return;
25     }
26      
27     for(int k=0; k<n; k++) {
28         if(sum+a[k]<=c && !vis[k]) {
29             vis[k] = 1;
30             dfs(k, sum+a[k]);
31             vis[k] = 0;
32         }
33     }
34 }
35  
36 int main()
37 {
38     ios::sync_with_stdio(false);
39     
40     while(cin>>n>>c)
41     {
42         can=0;
43         LL sum=0;
44         for(int i=0; i<n; i++) {
45             cin>>a[i], vis[i]=0;
46             sum += a[i];
47         }
48         if(sum < c) {
49             cout<<"No Solution!"<<endl;
50             continue;
51         }
52         dfs(0,0);
53         if(!can) cout<<"No Solution!"<<endl; 
54     }
55 }

 

 

这里也附上动规的代码,不能AC,但仍未一种想法。

 1 #include<iostream>
 2 #include<stack>
 3 #include<algorithm>
 4 using namespace std;
 5 const int MAX = 7003
 6 int dp[MAX][MAX];
 7 int p[MAX];
 8 int n,m;
 9 stack<int> goods;
10 
11 int main() {
12     cin>>m>>n;
13     for (int i = 1; i <= m; i++)
14         cin >> p[i];
15     for (int i = 1; i <= m; i++) {
16         for (int j = 1; j <= n; j++) {
17             dp[i][j] = (i == 1 ? 0 : dp[i - 1][j]);
18             if (j >= p[i]) {
19                 dp[i][j] = max(dp[i][j], dp[i - 1][j - p[i]] + p[i]);
20             }
21         }
22     }
23     
24     for (int i = m; i > 0; i--)
25         for(int j=0;j<=n;j++){
26             if (dp[i][n] - p[i] == dp[i - 1][j]) {
27                 goods.push(p[i]);
28                 n = j;
29             }
30         }
31     
32     cout<<goods.top();
33     goods.pop();
34     
35     while(!goods.empty()) {
36         cout<<' '<<goods.top();
37         goods.pop();
38     }
39     cout<<endl;
40     return 0;
41 }

 

转载于:https://www.cnblogs.com/liubilan/p/9394846.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值