DFS—找数字和

Posted asdfknjhu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DFS—找数字和相关的知识,希望对你有一定的参考价值。

题目: http://www.fjutacm.com/Contest.jsp?cid=860#P3

 

代码

 一,

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<queue>
#include<string.h>
using namespace std;
int map[30], vis[30], way[30];
int n, k;
queue<int>q;
int flag = 0, sum = 0;
void DFS(int j,int res)
{
	if (flag == 1)
		return;
	if (sum > k)
		return;
	if (sum == k)
	{
		flag = 1;
		printf("YES
");
		for (int i = 0; i < res ; i++)
			printf("%d ", way[i]);
		puts("");
		return;
	}
	for (int i = 0; i < n; i++)
	{
		if (vis[i] == 0)
		{
			vis[i] = 1;
			way[res] = map[i];
			sum += map[i];
			DFS(i + 1, res + 1);
			vis[i] = 0;
			sum -= map[i];
		}
	}
}
int main(void)
{
	while (scanf("%d%d", &n, &k) != EOF)
	{
		for (int i = 0; i < n; i++)
		{
			scanf("%d", &map[i]);
		}
		DFS(0, 0);
		if (flag == 0)
			printf("NO
");
		memset(way, 0, sizeof(way));
		memset(vis, 0, sizeof(vis));
		flag = 0, sum = 0;	
	}
}

① 这种需要记录路径的,好像只能利用递归的回溯来记录,

如果是使用栈的话,因为要同时压好几个数进栈,如果直接记录的画,就把同级的结点给记录上了,这样就错了,

但如果是递归的话,因为不用压栈,他直接回溯回来使用数据,自然不用把数据压入栈中。

现在我也不知道有没有办法可以解决这个问题,就只能用递归。

 

② 注意回溯时,要把改变的条件改回来。

像这一段,

i 是函数传参时直接改变,回溯时就自己变回来了,不用改变

而数组 vis 和 数字 sum 不是 参数,无论你函数调用多少次,他还是不会变,所以,必须在它回溯时给减回来

if (vis[i] == 0)
{
  vis[i] = 1;
  way[res] = map[i];
  sum += map[i];
  DFS(i + 1, res + 1);
  vis[i] = 0;
  sum -= map[i];
}

 

二,

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<stack>
using namespace std;
stack<int>s;
int n, k, a[30];
bool DFS(int i, int sum)                     
{
    if (sum > k)
        return false;
    if (i == n)                                   
        return k == sum;
    if (DFS(i + 1, sum + a[i])) //选 a[i]
    {
        s.push(a[i]);
        return true;
    }
    if (DFS(i + 1, sum))   //不选 a[i]
        return true;
    return false;
}
int main(void)
{
    while (scanf("%d%d", &n, &k) != EOF)
    {
        for (int i = 0; i < n; i++)
        {
            scanf("%d", &a[i]);
        }
        if (DFS(0, 0))
        {
            printf("YES
");
            while (!s.empty())
            {
                printf("%d ", s.top());
                s.pop();
            }puts("");
        }
        else
            printf("NO
");
    }
    return 0;
}

 

① 就是看到这个递归式才想起来这题的判断可以用 dp 做,不过储存路径还得是 DFS 才可以

 

 

三,

技术图片
 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include<stdio.h>
 3 #include<stdlib.h>
 4 #include<string.h>
 5 bool state[25];
 6 int a[25], k;
 7 int dfs(int sum, int n)
 8 {
 9     if (sum == k)   // 找到了,开始回溯
10         return 1;
11     if (n == 0)   // 找完了,开始回溯
12         return 0;
13 
14     while (n)
15     {
16         if (dfs(sum + a[n], n - 1))   // 如果是找到了结果的回溯,才记录
17         {
18             state[n] = 1;
19             return 1;
20         }
21         n--;
22     }
23     
24 }
25 int main(void)
26 {
27     int i, flag, n;
28     while (scanf("%d%d", &n, &k) != EOF)
29     {
30         memset(state, 0, 25);
31         for (i = 1; i <= n; i++)
32             scanf("%d", &a[i]);
33         if (dfs(0, n))
34         {
35             printf("YES
");
36             for (i = 1, flag = 0; i <= n; i++)
37                 if (state[i])
38                     printf("%d ", a[i]);
39             printf("
");
40         }
41         else
42             printf("NO
");
43     }
44     return 0;
45 }
View Code

 

以上是关于DFS—找数字和的主要内容,如果未能解决你的问题,请参考以下文章

找素数(一些数任意组合,DFS)

dfs模板找起点到终点的所有可能路径

JavaScript笔试题(js高级代码片段)

*** Bool 编码为数字属性列表片段。属性列表编码器

调用 onCreateView() 之前出现“找不到片段 id 的视图”错误

10个JavaScript代码片段,使你更加容易前端开发。