Zeta_c 搜索练习

在这里插入图片描述

N皇后问题

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 22760 Accepted Submission(s): 10136

Problem Description
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。

Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。

Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。

Sample Input
1
8
5
0

Sample Output
1
92
10

#include<bits/stdc++.h>
using namespace std;
int n, tot=0;
int col[12]={0};
bool check(int c,int r){
    for(int i = 0; i < r; i++)
        if(col[i] == c || (abs(col[i]-c) == abs(i-r))) return false;
    return true;
}
void DFS(int r){
    if(r==n){
        tot++;
        return;
    }
    for(int c = 0;c<n;c++){
        if(check(c,r)){
            col[r]=c;
            DFS(r+1);
        }
    }
}

int main(){
    int ans[12] = {0};
    for(n =0;n <= 10;n++){
        memset(col, 0,sizeof(col));
        tot=0;
        DFS(0);
        ans[n] = tot;
    }
    while(cin>>n){
        if(n==0) return 0;
        cout<<ans[n]<<endl;
    }
    return 0;
}

P1443 马的遍历

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int n, m, fx, fy;
int a[400 + 5][400 + 5];
int dir[8][2] = { {-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2} };
struct node {
    int x, y;
};
void bfs(int dx, int dy) {
    queue<node> q;
    node start, next;
    start.x = dx;
    start.y = dy;
    q.push(start);
    while (!q.empty()) {
        start = q.front();
        q.pop();
        for (int i = 0; i < 8; i++) {
            next.x = start.x + dir[i][0];
            next.y = start.y + dir[i][1];
            if (next.x <= 0 || next.x > n || next.y <= 0 || next.y > m || a[next.x][next.y] != 0 || (next.x == dx && next.y == dy)) continue;
            a[next.x][next.y]=a[start.x][start.y]+1;
            q.push(next);
        }
    }
}

int main() {
    cin >> n >> m >> fx >> fy;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) a[i][j] = 0;
    }
    bfs(fx, fy);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (a[i][j] != 0 || (i == fx && j == fy)) printf("%-5d", a[i][j]);
            else printf("%-5d", -1);
        }
        cout << endl;
    }
    return 0;
}


P1135 奇怪的电梯

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int n, a, b;
int k[200+5],vis[200+5];
void bfs(int da, int db) {
    queue<int> q;
    vis[da] = 0;
    int start,next;
    start=da;
    q.push(start);
    while (!q.empty()) {
        start = q.front();
        q.pop();
        for (int i = -1; i <=1; i+=2) {
            next = start + i*k[start];
            if (next <= 0 || next > n || vis[next] != -1) continue;
            vis[next] = vis[start]+1;
            if(next==db)break;
            q.push(next);
        }
    }
}
int main() {
    cin >> n >> a >> b;
    for (int i = 1; i <= n; i++) {
        cin>>k[i];
        vis[i]=-1;
    }
    bfs(a, b);
    cout<<vis[b]<<endl;
    return 0;
}

P2895 [USACO08FEB]Meteor Shower S

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;//无限大
int mp[302][302];//表示流星到达时间
bool v[302][302];//有无走过
struct point {
	int x,y,step;//步数也就是时间
};
int dx[]= {0,0,-1,1},dy[]= {-1,1,0,0};//四个方向 
int BFS(point a) {
	queue<point>q;
	q.push(a);
	v[a.x][a.y]=1;//标记为走过
	while(!q.empty()) {
		point b=q.front();
		q.pop();
		for(int d=0; d<4; ++d) {
			point c;
			c.x=b.x+dx[d],c.y=b.y+dy[d],c.step=b.step+1;
			if(c.x==-1||c.y==-1)continue;//判边界
			if(mp[c.x][c.y]==inf)return c.step;//永远不会有流星
			if(c.step<mp[c.x][c.y]&&!v[c.x][c.y]) {//在流星到达之前并且没走过
				q.push(c);
				v[c.x][c.y]=1;//标记为走过
			}
		}
	}
	return -1;
}
int main() {
	int m;
	scanf("%d",&m);
	memset(mp,0x3f,sizeof(mp));//由于是按字节赋值,刚好是mp[?][?]=inf
	for(int i=1,x,y,t; i<=m; ++i) {
		scanf("%d%d%d",&x,&y,&t);
		mp[x][y]=min(mp[x][y],t);
		for(int d=0; d<4; ++d) {
			if(x+dx[d]==-1||y+dy[d]==-1)continue;//判边界
			mp[x+dx[d]][y+dy[d]]=min(mp[x+dx[d]][y+dy[d]],t);
			//更新此位置流星最早到达时间
		}
	}
	printf("%d",BFS((point) {
		0,0,0
	}));
	//相当于
	//point a;
	//a.x=a.y=a.step=0;
	//printf("%d",BFS(a));
	return 0;
}

P1605 迷宫

在这里插入图片描述

#include<iostream>//个人建议不使用万能头文件,如果要使用万能头文件,就不能定义数组map;
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
int map[6][6];//地图;
bool temp[6][6];//走过的标记;
int dx[4]={0,0,1,-1};//打表;
int dy[4]={-1,1,0,0};//打表;
int total,fx,fy,sx,sy,T,n,m,l,r;//total计数器,fx,fy是终点坐标,sx,sy是起点坐标,T是障碍总数,n,m是地图的长和宽,l,r是障碍的横坐标和纵坐标;
void walk(int x,int y)//定义walk;
{
    if(x==fx&&y==fy)//fx表示结束x坐标,fy表示结束y坐标;
    {
        total++;//总数增加;
        return;//返回,继续搜索;
    }
    else
    {
        for(int i=0;i<=3;i++)//0——3是左,右,下,上四个方向;
        {
            if(temp[x+dx[i]][y+dy[i]]==0&&map[x+dx[i]][y+dy[i]]==1)//判断没有走过和没有障碍;
            {
                temp[x][y]=1;//走过的地方打上标记;
                walk(x+dx[i],y+dy[i]);
                temp[x][y]=0;//还原状态;
            }    
        } 
    }
}
int main()
{
    cin>>n>>m>>T;//n,m长度宽度,T障碍个数 
    for(int ix=1;ix<=n;ix++)
        for(int iy=1;iy<=m;iy++)
            map[ix][iy]=1;//把地图刷成1;
    cin>>sx>>sy;//起始x,y 
    cin>>fx>>fy;//结束x,y 
    for(int u=1;u<=T;u++)
    {
        cin>>l>>r;//l,r是障碍坐标;
        map[l][r]=0;
    }
    walk(sx,sy);
    cout<<total;//输出总数;
    return 0;
} 

一个基本的深搜模板

int search(int t)
{
    if(满足输出条件)
    {
        输出解;
    }
    else
    {
        for(int i=1;i<=尝试方法数;i++)
            if(满足进一步搜索条件)
            {
                为进一步搜索所需要的状态打上标记;
                search(t+1);
                恢复到打标记前的状态;//也就是说的{回溯一步}
            }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值