搜索(bfs,dfs)专题1--八皇后类型

1八皇后类型

模板
1判断边界
2剪枝
3尝试放入并判断,
4标记,最后回溯 (3 4两步可以调换)
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int A[10000000]={0};
int n;
int tot=0;
void search(int cur){
	if(cur == n) {//判断边界
		tot++;//当cur等于行数,那么就代表摆放成功
		if(tot<=3){
			for(int i=0;i<n;i++){
				if(i)cout<<" ";
				cout<<A[i];
			}
			cout<<endl;
		}
		return;
	}
	else for(int i=0;i<n;i++)
	{
		int ok = 1;
		A[cur] = i+1;//尝试把第cur行的皇后放入第i列	
		for(int j=0;j<cur;j++)
		{
			if(A[cur]==A[j]||cur-A[cur]==j-A[j]||cur+A[cur]==j+A[j])//判断是否同列同主对角线和同副对角线 
			{
				ok = 0;	break;//如果是,则不递归并退循环,回溯 
			}
		}
		if(ok) search(cur+1);//如果合法,则递归 
	}

}
 int main(){
 	cin>>n;
 	search(0);
 	cout<<tot;
 }

奇怪的电梯

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int r[100000]={0};
int s[100000]={0};
int n,a,b;
int sum=100000000;
void dfs(int cur,int click){
	if(cur==b){//1判断边界
		if(click<sum)sum=click;
	    return;
	}
	if(cur>b||cur<1)return;
	if(click>sum)return;//剪枝
	r[cur]=1;//标记,像此类操作少的,可以统一进行标记回溯.
	if(cur+s[cur]<=n&&!r[cur+s[cur]])
	dfs(cur+s[cur],click+1);
	if(cur-s[cur]>=1&&!r[cur-s[cur]])
    dfs(cur-s[cur],click+1);
    r[cur]=0;//回溯
}
int main(){
	cin>>n>>a>>b;
	for(int i=1;i<=n;i++)cin>>s[i];
	dfs(a,0);
	if(sum!=100000000){
		cout<<sum;
	}else cout<<"-1";
}

bfs版本:

#include<bits/stdc++.h>
using namespace std;
struct node{
	int cur;
	int step;
	node(int cur,int step):cur(cur),step(step){
	}
	node():cur(0),step(0){
	} 
};
queue<node> q;
int n,a,b;
int s[1000000]={0};
int vis[1000000]={0};
node t;
int main(){
	cin>>n>>a>>b;
	for(int i=1;i<=n;i++)cin>>s[i];
    q.push(node(a,0));
	while(!q.empty()){
		 t=q.front();
		q.pop();
		if(t.cur==b){
		
			break;
		}
		if(t.cur+s[t.cur]<=b&&!vis[t.cur+s[t.cur]]){
			q.push(node(t.cur+s[t.cur],t.step+1));
			vis[t.cur+s[t.cur]]=1;//bfs不用回溯,求的是最短路,只能到当前节点一次 
		}
		if(t.cur-s[t.cur]>=1&&!vis[t.cur-s[t.cur]]){
			q.push(node(t.cur-s[t.cur],t.step+1));
			vis[t.cur-s[t.cur]]=1;
		}
	}	
	if(t.cur==b)cout<<t.step;
	else cout<<"-1";
} 



/*
总结bfs:
1压入队头
2取队头
3判断
4遍历压入,标记vis 

*/ 


单词接龙

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
string str[20];
int use[20], length = 0, n;
int canlink(string str1, string str2) {
    for(int i = 1; i < min(str1.length(), str2.length()); i++) {//重叠长度从1开始,直到最短的字符串长度-1(因为不能包含)
        int flag = 1;
        for(int j = 0; j < i; j++)
            if(str1[str1.length() - i + j] != str2[j]) flag = 0;//逐个检测是否相等
        if(flag) return i;//检测完毕相等则立即return
    }
    return 0;//无重叠部分,返回0
}
void solve(string strnow, int lengthnow,int cur) {
	if(cur>2*n)return;
    length = max(lengthnow, length);//更新最大长度
    for(int i = 0; i < n; i++) {
        if(use[i] >= 2) continue;//该字符串使用次数需要小于2
        int c = canlink(strnow, str[i]);//获取重叠长度
        if(c > 0) {//有重叠部分就开始dfs
            use[i]++;
            solve(str[i], lengthnow + str[i].length() - c,cur+1);
            use[i]--;
        }
    }
}
main() {
    cin >> n;
    for(int i = 0; i <= n; i++) use[i] = 0, cin >> str[i];//str[n]为开始字符 
    solve(' '+str[n], 1,0);//有必要解释一下开始阶段。为了指定第一个字符,而且因为canlink需要重叠部分小于最短长度-1,所以要从前面添加一个无意义充长度的‘ ’。这样就强制了canlink函数比较最后一位。
    cout << length ;
}

选数字
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int n,k;
int a[1000000]={0};
int vis[100000]={0};
int sum=0;
void dfs(long long int l,int cur,int cnt){
	if(cur==k){//边界
		int i;
		for(i=2;i<=l;i++){
			if(l%i==0){
				break;
			}
		}
		if(l==i){
			sum++;
		}
		return;
	}
	if(cur>k)return;//剪枝
	for(int i=cnt;i<n;i++){
		if(!vis[i]){//判断
			l+=a[i];
			vis[i]=1;//标记
			dfs(l,cur+1,i+1);
			l-=a[i];
			vis[i]=0;//回溯
		} 
	}
}
int main(){
	cin>>n>>k;
	for(int i=0;i<n;i++)cin>>a[i];
	dfs(0,0,0);
	cout<<sum;
}

考前临时抱佛jiao
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int a[4][25]={0};
int s[4]={0};
int m,ans=0;
int l,r;
void dfs(int x,int y){
	if(y>s[x]){//边界
		m=min(m,max(l,r));//取左右脑最长的时间,m又要尽量小
		return;
	}
	//尝试往左右脑放题目;
	l+=a[x][y];
	dfs(x,y+1);
	l-=a[x][y];
	 r+=a[x][y];
	dfs(x,y+1);
	r-=a[x][y];
}
int main(){
	cin>>s[0]>>s[1]>>s[2]>>s[3];
	for(int i=0;i<4;i++){
		for(int j=0;j<s[i];j++){
			cin>>a[i][j];
		}
	}
	for(int i=0;i<4;i++){
		m=10000000;
        l=r=0;
		dfs(i,0);
		ans+=m;
	}
	cout<<ans;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值