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;
}
解题思路:一道经典的广度优先搜索,每次记下一步能到达的地方,对已经到过的地方不用再去循环
上代码!!!
#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;
}
解题思路:这个题从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;
}
这就是这几道题的基本思路与代码,题目不难,只为大家更好的练一下深搜广搜,理解思路!
同时给出一些进阶的题目,下一期继续进阶,大家加油!