栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

DFS之回溯算法的问题

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

DFS之回溯算法的问题

回溯算法的基本问题主要分为:1.排列问题2.组合问题

很多其他的算法题都基于这两种基本问题而产生

回溯问题的基本模板

基本模板:1.出口

                  2.判断部分/条件部分/访问设置部分

                  3.递归回溯部分

1.全排列问题

洛谷p1706

 

根据题意我们可知,这是一个排列问题,涉及到高中的A排列问题

排列的基本模型结构

 代码解析 1.初始化部分
#include 
using namespace std;
int ans[100] = { 0 };
int len;
int n;
int visit[10] = { 0 };

 len表示输入的最大数字,ans数组用来储存排列顺序

visit数组表示是否访问过(将前面已经出现过的数字设为1,而没有出现过的设为0)

2.main函数部分
int main()
{
	ans[0] = 0;
	cin >> n;			//输入n
	len = n;
	for (int i = 1;i <= n;i++)
	{
		dfs(i, 1);
		visit[i] = 0;
	}
}
 3.dfs函数部分

 dfs函数的定义设置为   void dfs(int i,int lenth)

i   表示要插入的数字          lenth表示要插入在数组的哪一个位置

在main函数中有一个循环,用来选择插入1-n中的数字

基本思路(伪代码)
  •  void dfs(int i,int lenth)
  • {         
  • if(出界   | |  lenth超过最大长度len  | |  这个数字访问过了  )
  •         return ;                                                //dfs的基本出口
  • 这个数字我取过了
  • 把数字插入到这个位置
  • if(lenth== 最大长度)
  • {         输出此时的排列顺序
  •           return;
  • }
  • 递归加回溯
  • }

 

void dfs(int z, int lenth)
{
	
	if (z > n || lenth > n||visit[z])
		return;
	ans[lenth] = z;
	if (lenth == len)
	{
		for (int i = 1;i <= len;i++)
			cout << "    " << ans[i];
		cout << 'n';
		return;
	}
	visit[z] = 1;

 

递归回溯部分

if(i没有访问过)

{        

        visit【i】=1;

        dfs(i,lenth+1);                //递归插入

        visit【i】=0;                         //回溯

}

for (int i = 1;i <= n;i++)
	{
		if (!visit[i])
		{
			dfs(i, lenth + 1);
			
			
			visit[i] = 0;
		}
	}
	ans[lenth] = 0;
}
2.组合问题 

 题目要求:按照字典序输出

 

 基本思路:找到最小的组合情况并且按照字典序的大小顺序输出

  • dfs(int n,int lenth)
  • {
  •     越界或者超出长度或者前面的数字==n
  •               --》出口;
  •     ans[lenth]=n;
  •     判断饲料总和是否满足于最小维生素要求
  •              判断是否满足最小长度(最少的饲料种类)
  •                      满足的话替换,不满足-》出口
  •    
  • visit[i]=1;               //收录这个数字        
  •  dfs(i+1,lenth);       //平替
  •  visit[I+1]=0;
  •  ans[lenth]=i;     //回溯
  • dfs(i+1,len);//顺替
  • }
 1.初始化
#include 
using namespace std;

int v;									//维生素的种类
int g;									//饲料的种类
int V[260] = { 0 };						//需要的维生素量
int feed[160][260] = { 0 };				//饲料
int visit[160] = { 0 };							//访问数组
int c[26];							//c是寄存数据数组(最多有25种维生素)
int t = 1;
int ans[16] = { 0 };					//最后的答案数组,寄存的是下标
int minl = 1e9;
int b[16] = { 0 };
2.main函数
int main()
{	
	int i, j;
	cin >> v;
	for (i = 1;i <= v;i++)
		cin >> V[i];
	cin >> g;
	for (i = 1;i <= g;i++)
		for (j = 1;j <= v;j++)
			cin >> feed[i][j];
	dfs(1, 0);
	cout << minl+1 << " ";
	for (i = 0;i < minl + 1;i++)
		cout << ans[i] << " ";
	
}
3.判断部分
bool Judge(int lenth)
{
	memset(c, 0, sizeof(c));
	for (int i = 0;i <= lenth;i++)
		for (int j = 1;j <= v;j++)
			c[j] += feed[b[i]][j];
	for (int i = 1;i <= v;i++)
		if (c[i] < V[i])
			return false;
	return true;
}
bool check()									//判断b是否比ans小
{
	int i = 0;
	int D_value=100;
	while (b[i] == ans[i]) { i++; }
	D_value = b[i] - ans[i];
	if (D_value > 0)	return  false;
	else return true;
}
4.dfs递归部分
void dfs(int i, int lenth)
{
	if (i > g || lenth > g||visit[i])			//越界return
		return;			
	b[lenth] = i;		
	if (lenth <= minl)
	{
		if (Judge(lenth))
		{
			if (lenth < minl) {
				minl = lenth;
				for (int i = 0;i <= lenth;i++)
					ans[i] = b[i];
				return;
			}
			if (lenth == minl)
				if (check())
				{
					for (int i = 0;i <= lenth;i++)
						ans[i] = b[i];
					return;
				}
		}
	}
	else return;
	visit[i] = 1;
	dfs(i + 1, lenth);
	b[lenth] = i;
	visit[i+1] = 0;
	dfs(i + 1, lenth + 1);

}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/296262.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号