深度优先搜索笔记1-数字组合问题

《啊哈,算法》中将的深度优先搜索挺好,做个笔记。

问题1:

使用数字1-9组成xxx-xxx=xxx等式,每个数字只能使用一次。

分析:

使用枚举法可以实现,但是需要时间复杂度很高,谁用深度优先搜索比较合适。深度优先搜索的关键在于:解决当下该怎么做,至于下一步该怎么做与当下该怎么做是一样的。将数字1-9比作手里的牌,要发到1-9号箱子里面。需要实现的深度优先搜索的函数dfs(step)确定走到第step个箱子前需要做什么,伪代码:

void dfs(int step)
{
   判断边界
   尝试每一种可能
   for(int i=1;i<=n;i++)
   {
      继续下一步
      dfs(step+1); 
   }
   return;
}

代码

#include<iostream>
#include<vector>

using namespace std;

int a[10], book[10], total = 0; //a数组代表盒子,book数组标记手里的牌是否已经被发出去,total代表方法数


void dfs(int step)
{
    if (step == 10)//如果step=10说明手里的牌已经发完了,可以判断这次排列是否满足要求
    {
        if (a[1] * 100 + a[2] * 10 + a[3] + a[4] * 100 + a[5] * 10 + a[6] == a[7] * 100 + a[8] * 10 + a[9])
        {
            total++;
            printf("method %-3d: %d%d%d+%d%d%d=%d%d%d\n",total,a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
        }
        return;//返回这次函数调用
    }

    for (int i = 1; i <= 9; i++)//走到第step个盒子面前,依次尝试手里的牌(没有被发出去)
    {
        if (book[i] == 0)//等于0说明该牌没有被发出去,还在手里
        {
            a[step] = i;//将这张牌放到盒子里
            book[i] = 1;//标记这张牌已经被发出去了
            dfs(step + 1);//走到下一个盒子发牌
            book[i] = 0;//将发出的这张牌取消标记,因为再次返回到这个盒子时,要尝试其他的牌,这张牌可以用于后续盒子发牌
        }
    }
    return;//处理完成后返回
}
int main()
{
    dfs(1);
    system("pause");
    return 0;
}

这里写图片描述

问题2

输入两个整数 n 和 m,从数列1,2,3…….n 中随意取几个数,使其和等于 m,要求将其中所有的可能组合列出来

输入描述

每个测试输入包含2个整数,n和m

输出描述

按每个组合的字典序排列输出,每行输出一种组合

如:
输入:
5 5
输出:
5
1 4
2 3

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

typedef struct Data
{
    int n;
    int m;
    vector<int> book;
    vector<int> box;
};

void dfs(Data& data,int numOfBox,int step,vector<vector<int>>& result)
{
    if (step == numOfBox)
    {
        int sum = 0;
        for (int i = 0; i <numOfBox; i++)
        {
            sum+=data.box[i];
        }
        if (sum == data.m)
        {
            result.push_back(data.box);
        }
        return;
    }

    int start = 1;
    for (int i = data.book.size() - 1; i >= 1; i--)
    {
        if (data.book[i] == 1)
        {
            start = i;
            break;
        }
    }

    for (int i = start; i <= data.n; i++)
    {
        if (data.book[i] == 0)
        {
            data.book[i] = 1;
            data.box.push_back(i);
            dfs(data, numOfBox, step + 1,result);

            data.book[i] = 0;
            data.box.pop_back();
        }

    }
    return;
}

void show_1(vector<vector<int>>& v)
{
    for (int i = 0; i < v.size(); i++)
    {
        for (int j = 0; j < v[i].size(); j++)
        {
            cout << v[i][j] << " ";
        }
        cout << endl;
    }
}

void dealResult(vector<vector<int>>& v)
{

}

int main()
{
    Data data;
    vector<vector<int>> result,final;
    cin >> data.n>>data.m;
    for (int i = 0; i <=data.n; i++)
    {
        data.book.push_back(0);
    }
    int sum=0,num;
    for (int i = 1; i < data.n; i++)
    {
        sum += i;
        if (sum >= data.m)
        {
            num = i;
            break;
        }
    }
    if (sum < data.m)
    {
        cerr << "Error: m is too big" << endl;
        system("pause");
        exit(1);
    }
    for (int i =1; i <= num; i++)
    {
        dfs(data, i, 0, result);
    }
    show_1(result);
    system("pause");
    return 0;
}

这里写图片描述

参考文献:《啊哈,算法》–啊哈磊

猜你喜欢

转载自blog.csdn.net/shuoyueqishilove/article/details/82379536
今日推荐