题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=927
题目的意思很是简单,问,我们能不能从一个集合里面找出一些数的和等于一个值。该集合里面最多有20个数。直接dfs求解之。。表示刚开始写dfs还是有很多修改的地方。
对于这题。。我刚开始是这样搜的。。看下图:
比如这组数据:
4
1 2 4 7
13
图是手机拍的,自己画的比较挫。。见谅。。
然后,我们就需要根据他搜的顺序的有序性。来进行剪枝。。。
什么叫做他的有序性呢?? 就是说我们搜的这个序列的从前往后的。。。。 那么我们可以记录一个起始点来进行搜索。。
如下图:
Code:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define CLR(arr, val) memset(arr, val, sizeof(arr))
const int N = 25;
const int INF = 0x3f3f3f3f;
int a[N], over, n;
bool vis[N], flag;
void dfs(int sum, int k)
{
if(flag) return ;
if(sum == over){
flag = true;
return ;
}
if(k >= n) return;
if(sum > over) return ;
for(int i = k ; i < n; i ++){
if(!vis[i]){
vis[i] = true;
dfs(sum + a[i], i + 1);
vis[i] = false;
}
}
}
int main()
{
// freopen("1.txt", "r", stdin);
while(~scanf("%d", &n)){
for(int i = 0; i < n; i ++){
scanf("%d", &a[i]);
}
scanf("%d", &over);
CLR(vis, false);
flag = false;
dfs(0, 0);
if(flag) puts("Of course,I can!");
else puts("Sorry,I can't!");
}
return 0;
}
其实还可以搜一颗类似二叉树。。
Code:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
using namespace std;
const int N = 24;
int a[N], over, n;
bool flag;
void dfs(int k, int sum)
{
if(sum > over) return ;
if(flag) return ;
if(k > n) return ;
if(sum == over){
flag = true;
return;
}
dfs( k + 1, sum + a[k]);
dfs(k + 1, sum);
}
int main()
{
// freopen("1.txt", "r", stdin);
while(~scanf("%d", &n)){
for(int i = 0; i < n; i ++){
scanf("%d", &a[i]);
}
scanf("%d", &over);
flag = false;
dfs(0, 0);
flag ? puts("Of course,I can!") : puts("Sorry,I can't!");
}
return 0;
}
能够理解dfs的搜索路径。。对于写出来会有更好的帮助。。。一步一步来。。
Nyoj 1058 也是类似的问题。。come on。。