部分和问题

给定一组数,判断是否可以从中取出若干数,是他们的和恰好为一个数。
Example:
input
4 13
2 3 4 7
ouput
Yes

每个数都会有两个状态,加上或者不加上,这组样例中有四个数,每个数两个状态,也就是说最后的加起来的结果会有2的4次方(16)种。

Codes

#include<bits/stdc++.h>
using namespace std;
int n,k,a[10000];
bool dfs(int i,int sum)
{
if(i==n)
{
// puts("mmp");
return sum==k;
}
if(dfs(i+1,sum))
{
// puts("a");
return 1;
}
if(dfs(i+1,sum+a[i]))
{
// puts("b");
return 1;
}
}
int main()
{
cin>>n>>k;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
if(dfs(0,0)) puts("Yes");
else puts("No");
return 0;
}

只看代码会很难理解,一重一重的递归,但这还只是最简单的一种。为了更好的让自己理解,我将这个样例的所有情况都列了出来。

DFS(0,0)
DFS(1,0)
DFS(2,0)
DFS(3,0)
DFS(4,0) return 0
DFS(4,7) return 0
DFS(3,4)
DFS(4,4) return 0
DFS(4,11) return 0
DFS(2,3)
DFS(3,3)
DFS(4,3) return 0
DFS(4,10) return 0
DFS(3,7)
DFS(4,7) return 0
DFS(4,14) return 0
DFS(1,2)
DFS(2,2)
DFS(3,2)
DFS(4,2) return 0
DFS(4,9) return 0
DFS(3,6)
DFS(4,6) return 0
DFS(4,13) return 0
DFS(2,5)
DFS(3,5)
DFS(4,5) return 0
DFS(4,12) return 0
DFS(3,9)
DFS(4,9) return 0
DFS(4,16) return 0

我又将这16种情况,用图的方式表示了出来

0
2 0
5 2 3 0
9 5 6 2 7 3 4 0
16 9 12 5 13 6 9 2 14 7 10 3 11 4 7 0

这时我发现程序跟画出来的是一模一样的。

可是还是不很理解,于是我运行起来程序,并且在每次递归中加入了可以看到的元素,输出a,b或者mmp啊什么的。一起来看看效果
input:
4 13
2 3 4 7


mmp个数数出来是12个,a,b出现的顺序是b,b,a,b

input:
4 0
2 3 4 7


mmp个数数出来是1个,a,b出现的顺序是a,a,a,a

mmp代表的个数就是出现sum==k的时候前面进行的递归的次数,a代表的是第i位的数状态是不加,b代表的是第i位的数状态是加

也就这样了,DFS慢慢来,这样跑程序我觉得会加深理解啊哈🎈。

Nickname
Email
Website
0 comments