DFS合集(蓝桥杯C/C++)(随时更新,更新时间:2023.3.6)

目录

1  数的全排列(模板)

2  n皇后问题

3  2n皇后问题

4  车的放置

5  粘木棍

6  24点

7  五星填数


1  数的全排列(模板)

#include <bits/stdc++.h>
using namespace std;

int a[10]={1,2,3,4,5,6,7,8,9,10};
int b[10];
bool vis[10];

void dfs(int s)
{
	if(s==6)
	{
		for(int i=0;i<6;i++)
		{
			cout<<b[i]<<' '; 
		}
		cout<<endl;
		return;
	}
	for(int i=0;i<6;i++)
	{
		if(!vis[i])
		{
			vis[i]=true;
			b[s]=a[i];
			dfs(s+1);
			vis[i]=false;
		}
	}
} 

int main()
{
	dfs(0);
	return 0;
}

2  n皇后问题

特点:充分运用全排列知识,每一行只能放一个皇后,全排列保证每一列只能出现一个皇后,斜线再进行后续处理

3  2n皇后问题

特点:在n皇后的基础上需要再次运用全排列,属于嵌套搜索

原题:

2n皇后问题(蓝桥杯基础练习C/C++)_菜只因C的博客-CSDN博客_2n皇后问题蓝桥杯2n皇后问题(蓝桥杯基础练习C/C++)https://blog.csdn.net/m0_71934846/article/details/128772257代码:

#include <bits/stdc++.h>
using namespace std;
 
int mp[9][9];//初始化地图 
bool visblack[9];//黑皇后是否用到 
bool viswhite[9];//白皇后是否用到 
int black[9],white[9];//皇后放到第几列 *解释1* 
int ans;//答案 
int cnt,cnt1,cnt2,n,jishu[30],temp;//计数用 
int j,i;//循环变量 
void dfswhite(int p)//后放 
{
	if(p==n+1)//设置边界 
	{
		cnt=0,cnt1=0,cnt2=0,temp=0;//计数用的变量必须归零 
		memset(jishu,0,sizeof(jishu));
		for(int j=1;j<=n;j++)
		{
			if(mp[j][white[j]]==1)//检测该位置是否能放皇后 
			{
				cnt++;
			}
			for(int k=0;k<=n-1;k++)//*解释2* *解释3* 
			{
				if(j+white[j]==n+1+k)  jishu[k]++;//0ton-1
			}
			for(int k=1;k<=n-1;k++)
			{
				if(j+white[j]==n+1-k)  jishu[n+k-1]++;//nto2n-2
			}
			for(int k=0;k<=n-1;k++)
			{
				if(white[j]==j+k)  jishu[2*n-1+k]++;//2n-1to3n-1
			}
			for(int k=1;k<=n-1;k++)
			{
				if(white[j]==j-k)  jishu[3*n+k-2]++;//3nto4n-1
			}
		}
		/*for(int j=1;j<=50;j++)//测试用 
		{
			cout<<jishu[j]<<' ';
		}
		cout<<endl;*/
		for(int k=0;k<=29;k++)
		{
			if(jishu[k]>=2)  cnt--;
		}
		if(cnt==n)
		{
			/*for(int j=1;j<=n;j++)
			{
				cout<<"bai"<<white[j]<<' ';
			}
			cout<<endl;*/
			ans++;
		}  
		return;
	}
	
	for(int i=1;i<=n;i++)//dfs全排列*解释4* 
	{
		if(!viswhite[i])
		{
			viswhite[i]=true;
			white[p]=i;
			dfswhite(p+1);
			viswhite[i]=false;
		}
	}
	return;
}
 
void dfsblack(int s)//先放 
{
	if(s==n+1)
	{
		cnt=0,cnt1=0,cnt2=0,temp=0;
		memset(jishu,0,sizeof(jishu));
		for(int i=1;i<=n;i++)
		{
			if(mp[i][black[i]]==1)
			{
				cnt++;
			} 
			for(int k=0;k<=n-1;k++)
			{
				if(i+black[i]==n+1+k)  jishu[k]++;
			}
			for(int k=1;k<=n-1;k++)
			{
				if(i+black[i]==n+1-k)  jishu[n+k-1]++;
			}
			for(int k=0;k<=n-1;k++)
			{
				if(black[i]==i+k)  jishu[2*n-1+k]++;
			}
			for(int k=1;k<=n-1;k++)
			{
				if(black[i]==i-k)  jishu[3*n+k-2]++;
			} 
		}
		/*for(int j=1;j<=50;j++)
		{
			cout<<jishu[j]<<' ';
		}
		cout<<endl;*/
		for(int k=0;k<=29;k++)
		{
			if(jishu[k]>=2)  cnt--;
		}
		if(cnt==n)
		{
			/*for(int i=1;i<=n;i++)
			{
				cout<<"hei"<<black[i]<<' ';
			}
			cout<<endl;*/
			for(int i=1;i<=n;i++)
			{
				mp[i][black[i]]=0;
			}
			//cout<<"开始"<<endl;
			dfswhite(1);
			//cout<<"结束"<<endl;
			for(int i=1;i<=n;i++)
			{
				mp[i][black[i]]=1;
			}
		}  
		return;
	}
	
	for(int i=1;i<=n;i++)
	{
		if(!visblack[i])
		{
			visblack[i]=true;
			black[s]=i;
			dfsblack(s+1);
			visblack[i]=false;
		}
	}
	return;
}
 
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>mp[i][j];
		}
	}
	dfsblack(1);
	cout<<ans;
	return 0;
} 

4  车的放置

特点:在n皇后问题上进行修改,不限制放置数量,需要搜索次数更多

原题:

车的放置(蓝桥杯算法训练C/C++)_菜只因C的博客-CSDN博客车的放置(蓝桥杯算法训练C/C++)https://blog.csdn.net/m0_71934846/article/details/128876478?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22128876478%22%2C%22source%22%3A%22m0_71934846%22%7D代码:

#include  <bits/stdc++.h>
using namespace std;
int N;
long long ans=0; 
bool vis[10]; 
void dfs(int s)
{
    if(s>N)
	{
		ans++;
		return ;
	} 
    for(int i=1;i<=N;i++)
    {
    	if(!vis[i]) 
        {
            vis[i]=true; 
    
            dfs(s+1); 
            vis[i]=false; 
        }
	}  
    dfs(s+1); //不一定从第s行开始放(即第s行没有也可以),从s+1行开始放也可以
}
int main()
{
    cin>>N;
    dfs(1);
    cout<<ans;
    return 0;
}

5  粘木棍

特点:把n个数据放入m个位置中加和(其中n>m)

原题:

粘木棍(蓝桥杯算法训练C/C++)_菜只因C的博客-CSDN博客粘木棍(蓝桥杯算法训练C/C++)https://blog.csdn.net/m0_71934846/article/details/128876620?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22128876620%22%2C%22source%22%3A%22m0_71934846%22%7D代码:

#include<bits/stdc++.h>
using namespace std;
int a[10];
int n,m;
int ans=INT_MAX;
bool vis[10];
int sum[10];
void dfs(int k)
{
	if(k>=n+1)
	{
		int maxsum=0,minsum=INT_MAX;
		for(int i=1;i<=m;i++)
		{
			maxsum=max(maxsum,sum[i]);
			minsum=min(minsum,sum[i]);
		}
		ans=min(maxsum-minsum,ans);
		return ;
	}
	for(int i=k;i<=n;i++)   //注意这个地方是从k开始的,防止重复计算,剪枝,否则得90分 
	{
		if(!vis[i])
		{
			vis[i]=true;       
			for(int j=1;j<=m;j++)
			{
				sum[j]+=a[i];
				dfs(k+1);
				sum[j]-=a[i]; 
			}
			vis[i]=false;
		}
	} 
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	dfs(1);
	cout<<ans;
	return 0;
 } 

6  24点

特点:需要两个数两个数搜索

原题:

https://blog.csdn.net/m0_71934846/article/details/128878572https://blog.csdn.net/m0_71934846/article/details/128878572代码:

#include <bits/stdc++.h>
using namespace std;

int n;					
int nums[4];			
int ans;				

void f(int nums[], int n)
{

	if(n==1)//边界 
	{
		if(nums[n-1]<=24)
		{
			ans=max(ans,nums[n-1]);
		}
		return ;
	}
	
	//遍历两个数的组合 
	for(int i=0; i<n-1; i++)
	{
		for(int j=i+1; j<n; j++)
		{
			int a=nums[i], b=nums[j];
			
			nums[j] = a + b;//不断计算当前值放给nums[j]	
			nums[i] = nums[n-1];//不断把未计算的值放给nums[i] 
			f(nums, n-1);
			
			nums[j] = a * b;
			nums[i] = nums[n-1];
			f(nums, n-1);
			
			nums[j] = a - b;		
			nums[i] = nums[n-1];
			f(nums, n-1);
			
			nums[j] = b - a;
			nums[i] = nums[n-1];
			f(nums, n-1);
			
			if(b!=0 && a%b==0)
			{		
				nums[j] = a / b;
				nums[i] = nums[n-1];
				f(nums, n-1);
			}
			
			if(a!=0 && b%a==0)
			{
				nums[j] = b / a;
				nums[i] = nums[n-1];
				f(nums, n-1);
			}
			
			nums[i] = a;//回溯 
			nums[j] = b;
		}
	} 
}

int main()
{	
	cin>>n;
	for(int i=0; i<n; i++)
	{
		for(int j=0; j<4; j++)
		{
			cin >> nums[j];
		}
		ans = 0;		
		f(nums, 4);
		cout<<ans<<endl;
	}
	return 0; 
} 

7  五星填数

特点:全排列+筛选

原题:https://blog.csdn.net/m0_71934846/article/details/129336863?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22129336863%22%2C%22source%22%3A%22m0_71934846%22%7Dicon-default.png?t=N176https://blog.csdn.net/m0_71934846/article/details/129336863?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22129336863%22%2C%22source%22%3A%22m0_71934846%22%7D代码:

#include <bits/stdc++.h>
using namespace std;
int a[10]={1,2,3,4,5,6,8,9,10,12};
int b[10];
bool vis[10];
int ans;
void dfs(int s,int step)
{
	if(s==step)
	{
		/*for(int i=0;i<step;i++)
		{
			printf("%d ",b[i]);
		}
		printf("\n");*/
		int t=b[0]+b[2]+b[5]+b[8];
		if(t==b[0]+b[3]+b[6]+b[9]&&t==b[1]+b[2]+b[3]+b[4]&&t==b[1]+b[5]+b[7]+b[9]&&t==b[4]+b[6]+b[7]+b[8]) ans++;
	}
	for(int i=0;i<10;i++)
	{
		if(!vis[i])
		{
			vis[i]=true;
			b[s]=a[i];
			dfs(s+1,step);
			vis[i]=false;
		}
	}
}
 
int main()
{
	dfs(0,10);
	printf("%d",ans/10);
	return 0;
}

  • 11
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜只因C

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值