深搜广搜题目练习(接上期)

1.[USACO1.5]八皇后 Checker Challenge - 洛谷

解题思路:由题可知每行每列以及每条正对角线与反对角线上都只能存在一个

利用两条对角线的横纵坐标和是一样的来解决问题(思想)+深度优先搜索(方法)

上代码!!!

//深度优先搜索
#include <stdio.h>
int a[1000];//存行的列数
int b[1000];//存列数的皇后数
int c[1000];//存反对角线的数量
int d[1000];//存对角线数量
int number,n=0;//行数以及符合条件的个数
void print(){
	if(n<=2){
    if(number>2){
        for(int i=1;i<=number;i++){
            printf("%d",a[i]);
            if(i==number){
                printf("\n");
            }else{
                printf(" ");
            }
        }
    }
}
    n++;
}

void search(int i){
    int j;
    for(j=1;j<=number;j++){
        if(b[j]==0&&c[i+j]==0&&d[i-j+number]==0){//判断是否符合条件
            a[i]=j;
            b[j]=1;
            c[i+j]=1;
            d[i-j+number]=1;//对符合条件的位置进行标记
            if(i==number){
                print();//循环到最后一行即为结束
            }else{
                search(i+1);//未结束就继续走到下一行
            }
            b[j]=0,c[i+j]=0,d[i-j+number]=0;//回溯回来,取消标记
        }
    }
    return;
}


int main(){
    scanf("%d",&number);
    search(1);//对第一行开始放置进行
    printf("%d",n);
    return 0;
}

2.马的遍历 - 洛谷

解题思路:一道经典的广度优先搜索,每次记下一步能到达的地方,对已经到过的地方不用再去循环

上代码!!!

#include <stdio.h>
int sign[401][401]={{0}};//进行标记步数的数组
int gx[8]={1,2,1,2,-1,-2,-1,-2};
int gy[8]={2,1,-2,-1,-2,-1,2,1};

struct gg{
    int x,y;
}s[160000],temp;//存坐标的数组
int n,m;
void bfs(int x,int y)
{
    int tail=1,head=1;
    s[1].x=x,s[1].y=y;
    while(tail>=head){//数组模拟队列
        temp=s[head++];
        //if(sign[temp.x][temp.y]==0) continue;
        for(int i=0;i<8;i++){
            int nx=temp.x+gx[i];
            int ny=temp.y+gy[i];//生成新的坐标
            if(nx<=0||ny<=0||nx>n||ny>m||sign[nx][ny]) continue;
            sign[nx][ny]=sign[temp.x][temp.y]+1;//步数+1
            s[++tail].x=nx;
            s[tail].y=ny;
        }
    }
    
}
int main()
{
    int x,y;
    scanf("%d %d %d %d",&n,&m,&x,&y);
    sign[x][y]=1;
    bfs(x,y);
    
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
        	if(sign[i][j]==0) printf("-1 ");
        	else printf("%d ",sign[i][j]-1);   
        }
        printf("\n");
    }
    return 0;
}

3.奇怪的电梯 - 洛谷

解题思路:这个题从A到B无非就两种情况:

        (1.)如果走到一个到过的地方就不用再走,再走下去也是重复过程,无用功;

        (2.)向上向下两种选择,走到目的地返回;

上代码!!!

#include<bits/stdc++.h>
using namespace std;
int n,a,b,to[205];//存每节楼梯能走的楼数
bool vis[205];//用于判断是否到过这里
struct node{int id,step;}x;//id表示楼层号,step表示按钮次数
queue<node> q;//上面一题用数组模拟了队列,这里用队列演示一下,没学队列的小伙伴可以模仿上面试一试
int main()
{
	scanf("%d%d%d",&n,&a,&b);
	for(int i=1;i<=n;i++) scanf("%d",&to[i]);//存进数据
	q.push((node){a,0});//起点
	while(q.size())
	{
		x=q.front();
        q.pop();//取出来就踢出队列
		if(x.id==b) break;
		if(x.id+to[x.id]<=n&&!vis[x.id+to[x.id]])//判断没到过并且不能越界
		{
			q.push((node){x.id+to[x.id],x.step+1});//入队
			vis[x.id+to[x.id]]=1;
		}
		if(x.id-to[x.id]>=1&&!vis[x.id-to[x.id]])//不越界并未到过
		{
			q.push((node){x.id-to[x.id],x.step+1});//入队
			vis[x.id-to[x.id]]=1;
		}
	}
	if(x.id==b) printf("%d",x.step);
	else printf("-1");//未循环到既是到不了
	return 0;
}

4.迷宫 - 洛谷

解题思路:本题也是一道非常经典的深搜,只是加了一个障碍条件

上代码!!!

#include <stdio.h>
int gx[4]={0,0,-1,1};
int gy[4]={1,-1,0,0};//四个方向
int j[6][6]={{0}};
int ans=0;//方法数
int used[6][6]={{0}};//判断是否到过的数组
void dfs(int x1,int y1,int x2,int y2,int n,int m)
{
    if(x1==x2&&y1==y2){
        ans++;
        return ;//达到目标,方法+1
    }
    for(int i=0;i<4;i++){
        int nx=x1+gx[i];
        int ny=y1+gy[i];//到达的坐标
        if(nx>n||nx==0||ny==0||ny>m||j[nx][ny]||used[nx][ny]) continue;//判断越界以及是否曾经到过+障碍
        used[nx][ny]=1;//标记为到过
        dfs(nx,ny,x2,y2,n,m);
        used[nx][ny]=0;//取消标记
    }
}
int main()
{
    int n,m,k,x1,y1,x2,y2,x,y;
    scanf("%d %d %d",&n,&m,&k);
    scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
    j[x1][y1]=1;
    for(int i=0;i<k;i++){
        scanf("%d %d",&x,&y);
        j[x][y]=1;//障碍物标记
    }
    dfs(x1,y1,x2,y2,n,m);
    printf("%d",ans);
    return 0;
}

这就是这几道题的基本思路与代码,题目不难,只为大家更好的练一下深搜广搜,理解思路!

同时给出一些进阶的题目,下一期继续进阶,大家加油!

1.[USACO08FEB]Meteor Shower S - 洛谷

2.[NOIP2002 提高组] 字串变换 - 洛谷

3.[USACO11OPEN]Corn Maze S - 洛谷

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

TV后台码农

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

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

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

打赏作者

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

抵扣说明:

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

余额充值