《啊哈,算法》中将的深度优先搜索挺好,做个笔记。
问题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;
}
参考文献:《啊哈,算法》–啊哈磊