目录
全排列问题
选书
八皇后 Checker Challenge
求细胞数量:
[USACO10OCT]Lake Counting S
扫雷游戏
拯救oibh总部
填涂颜色
海战
健康的荷斯坦奶牛 Healthy Holsteins
打开所有的灯
离开中山路
马的遍历
好奇怪的游戏
奇怪的电梯
路障
上学路线
回家
血色先锋队
代码1:dfs注意恢复现场,参看排列数字
#include
using namespace std;
const int N=10;
int n;
int path[N];
bool st[N];
void dfs(int u)
{
if(u==n)
{
for(int i=0;i>n;
dfs(0);
return 0;
}
两种情况返回!
代码2:函数
#include
using namespace std;
int a[10];
int main()
{
int n,i,j=1,k;
cin>>n;
for(i=1;i<=n;i++)
{
a[i]=n-i+1;
j*=i;
}
for(i=1;i<=j;i++)
{
next_permutation(a+1,a+n+1);
for(k=1;k<=n;k++)cout<<" "<
代码:dfs
#include
using namespace std;
int a[30][2],x,res;
bool b[30];
void dfs(int i)
{
if(i>x)
{
res++; //如果所有人都拿到了自己喜欢的书,方案数就加一
return ;
}
else
for(int j=0;j<=1;j++)
if(!b[a[i][j]]) //分别判断每个人喜欢的第一本和第二本书是否被别人拿走,如果没有,就把这本书给这个人
{
b[a[i][j]]=1;//把这本书值为已拿过
dfs(i+1); //递归下一人
b[a[i][j]]=0; //恢复现场
}
}
int main()
{
cin>>x;
if(x==0) //特判坑!
{
cout<<0;
return 0;
}
for(int i=1;i<=x;i++) cin>>a[i][0]>>a[i][1];
dfs(1);
cout<
代码:这道题可以参照一下皇后问题
#include
using namespace std;
const int N = 100;
int n,res;
int path[N];
char g[N][N];
bool col[N],dg[N],udg[N]; //col[N]列,dg[N]正对角线,udg[N]反对角线
void dfs(int u)
{
if(u==n)
{ //找到一组方案
res++;
if(res<=3)
{
for(int i=0;i>n;
for(int i=0;i
测试代码:
#include
using namespace std;
int n,m,ans=0;
int a[105][105];
bool used[105][105];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
void dfs(int x,int y)
{
used[x][y]=1;
for(int i=0;i<4;i++)
{
int nx=x+dx[i];
int ny=y+dy[i];
cout<<"nx="<>n>>m;
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%1d",&a[i][j]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(used[i][j]==0 && a[i][j]!=0)
{
cout<<"i="<
测试结果
递归过程:
代码:
#include
using namespace std;
int n,m,ans;
const int N=110;
int a[N][N]; //a数组存输入的数
bool st[N][N]; //st数组记录当前的数是否遍历过
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1}; //四个方向
void dfs(int x,int y)
{
st[x][y]=1; //表示已经遍历过
for(int i=0;i<4;i++)
{
int nx=x+dx[i]; //分别按上下左右四个方向进行遍历
int ny=y+dy[i];
if(a[nx][ny]==0 || st[nx][ny]==1) continue; //如果已经遍历过或者当前的数为0则直接遍历下一个方向
dfs(nx,ny); //如果当前的数不是0且没有遍历过,则进行递归处理
}
}
int main()
{
cin>>n>>m;
//memset(a,0,sizeof(a)); 对数组进行初始化,全局变量默认初始值为0
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%1d",&a[i][j]); //用scanf读入整数的时候可以控制读入的位数
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(st[i][j]==0 && a[i][j]!=0)
{
dfs(i,j);
ans++;
}
}
}
cout<
同细胞数量
代码:
#include
using namespace std;
const int N=110;
char a[N][N];
bool st[N][N];
int res,n,m;
int nx[8]={-1,1,0,0,-1,-1,1,1};//x方向
int ny[8]={0,0,-1,1,-1,1,-1,1};//y方向
void dfs(int x,int y)
{
st[x][y]=1;
for(int i=0;i<8;i++)
{
int dx=x+nx[i],dy=y+ny[i];
if(a[dx][dy]!='.'&&st[dx][dy]==0)dfs(dx,dy);
}
}
int main()
{
cin>>n>>m;
memset(a,'.',sizeof(a)); //注意初始化
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
//scanf("%s",&a[i][j]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]!='.'&&st[i][j]==0)
{
dfs(i,j);
res++;
}
}
}
cout<
代码:dfs
#include
using namespace std;
const int N=110;
char ch;
int a[N][N];
int n,m;
int nx[8]={-1,1,0,0,-1,-1,1,1};//x方向
int ny[8]={0,0,-1,1,-1,1,-1,1};//y方向
int dfs(int x,int y)
{
int res=0;
for(int i=0;i<8;i++)
{
int dx=x+nx[i],dy=y+ny[i];
if(a[dx][dy]==-1)res++;
}
return res;
}
int main()
{
cin>>n>>m;
memset(a,0,sizeof(a)); //注意初始化
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>ch;
if(ch=='*')a[i][j]=-1;
else if(ch=='?')a[i][j]=0;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]==0)
{
a[i][j]=dfs(i,j);
cout<
本来以为和细胞数量思路差不多,就是在遍历查询的时候统计一下四周是否有四个*,但是样例正确,代码全错
原因是因为考虑情况不全面,并不是相邻的四周有四个*才符合条件
例如下面的样例
其实这道题可以反过来思考就和细胞数量差不多了,dfs递归寻找出边界部分带有0的连通块,将其标记为*,最后遍历计算出剩下的0的数量即答案
代码:
#include
using namespace std;
int n,m,res;
const int N=510;
char a[N][N]; //a数组存输入的数
bool st[N][N]; //st数组记录当前的数是否遍历过
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1}; //四个方向
void dfs(int x,int y)
{
st[x][y]=1; //表示已经遍历过
a[x][y]='*'; //如果是'0'就变为'*'
for(int i=0;i<4;i++)
{
int nx=x+dx[i]; //分别按上下左右四个方向进行遍历
int ny=y+dy[i];
if(a[nx][ny]=='*' || st[nx][ny]==1) continue; //如果已经遍历过或者当前为'*'则直接遍历下一个方向
dfs(nx,ny); //如果当前的数不是'0'且没有遍历过,则进行递归处理
}
}
int main()
{
cin>>n>>m;
memset(a,'*',sizeof(a)); //对数组进行初始化,全局变量默认初始值为*
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
for(int i=1;i<=n;i++) //搜索第一列和最后一列的格子
{
if(a[i][1]=='0' && st[i][1]==0) //如果有能过的就搜索
dfs(i,1);
if(a[i][m]=='0' && st[i][m]==0)
dfs(i,m);
}
for(int i=1;i<=m;i++) //搜索第一行和最后一行的格子
{
if(a[1][i]=='0' && st[1][i]==0)
dfs(1,i);
if(a[n][i]=='0' && st[n][i]==0)
dfs(n,i);
}
for(int i=1;i<=n;i++) //最后搜索没有被淹的格子
for(int j=1;j<=m;j++)
if(a[i][j]=='0')res++;
cout<
思路和拯救oibh总部一样,但是要注意初始化,如果是将数组看成数字,会出现死循环,所以就把数组看成字符串
代码:
#include
using namespace std;
int n,m,res;
const int N=50;
char a[N][N]; //a数组存输入的数
bool st[N][N]; //st数组记录当前的数是否遍历过
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1}; //四个方向
void dfs(int x,int y)
{
st[x][y]=1; //表示已经遍历过
a[x][y]='3'; //如果是'0'就变为'3',便于区分
for(int i=0;i<4;i++)
{
int nx=x+dx[i]; //分别按上下左右四个方向进行遍历
int ny=y+dy[i];
if(a[nx][ny]=='0' && st[nx][ny]==0) dfs(nx,ny); //如果当前的数不是'0'且没有遍历过,则进行递归处理
}
}
int main()
{
cin>>n;
memset(a,'1',sizeof(a)); //对数组进行初始化,全局变量默认初始值为‘1’
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>a[i][j];
for(int i=1;i<=n;i++) //搜索第一列和最后一列的格子,第一行和最后一行的格子
{
if(a[i][1]=='0' && st[i][1]==0) //如果有能过的就搜索
dfs(i,1);
if(a[i][n]=='0' && st[i][n]==0)
dfs(i,n);
if(a[1][i]=='0' && st[1][i]==0)
dfs(1,i);
if(a[n][i]=='0' && st[n][i]==0)
dfs(n,i);
}
for(int i=1;i<=n;i++) //输出恢复不该变为3的0
{
for(int j=1;j<=n;j++)
{
if(a[i][j]=='0')
a[i][j]='2';
else if(a[i][j]=='3')
a[i][j]='0';
cout<
理解清楚题意中的方形:
不合法的情况,在 2*2 的矩阵中,只有这四种情况:
1.
##
#.
2.
##
.#
3.
.#
##
4.
#.
##
可以在开头时特判一下,不满足条件直接输出,否则记录一下出现了几个矩阵
如何记录矩阵?可以在搜到矩阵的左上角时,判断他的左侧和上侧是否不为#
代码:
#include
using namespace std;
const int N=1010;
char a[N][N];
int n,m,res;
bool check(int x,int y)
{
int k=0;
if(a[x][y]=='#')k++;
if(a[x+1][y]=='#')k++;
if(a[x][y+1]=='#')k++;
if(a[x+1][y+1]=='#')k++;
return k==3;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
cin>>a[i][j];
}
for(int i=1;i<=n;i++)//特殊情况的判断
{
for(int j=1;j<=m;j++)
{
if(check(i,j))
{
printf("Bad placement.");
return 0;
}
}
}
for(int i=1;i<=n;i++) //判断是否为矩阵,并记录答案
{
for(int j=1;j<=m;j++)
{
if(a[i][j]=='#'&&a[i][j-1]!='#'&&a[i-1][j]!='#')res++;
}
}
printf("There are %d ships.",res);
return 0;
}
一行一行地枚举,记录到res数组中,再判断符合条件的方案
代码:
#include
using namespace std;
int v,g,a[30],b[30][30],m=20,mx[30],res[30];
bool check(int x)
{
for(int i=1;i<=v;i++) //枚举牛每天需要的每种维他命的最小量
{
int sum=0; //别忘了初始化!!!
for(int j=1;j<=x;j++)
{
sum+=b[res[j]][i];//累加
}
if(sumg)//搜完了,不管它成功不成功我都要结束了,否则就会死循环。
{
if(check(z) && z>v;
for(int i=1;i<=v;i++) cin>>a[i];
cin>>g;
for(int i=1;i<=g;i++)
for(int j=1;j<=v;j++)
cin>>b[i][j];
dfs(1,0); //从每一行开始搜索
cout<
代码:dfs
#include
using namespace std;
int a[5][5],res=0,m=10;//定义变量
void dd(int x,int y)//处理按一次灯
{
a[x][y]=1-a[x][y]; //本身
a[x+1][y]=1-a[x+1][y]; //下
a[x][y+1]=1-a[x][y+1]; //右
a[x-1][y]=1-a[x-1][y]; //上
a[x][y-1]=1-a[x][y-1]; //左
}
void dfs(int k)
{
if(k>m) return;//限制,Mix不小于k的话会超时
int s=0;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
s+=a[i][j];
if(s==9)//判断都打开了
{
res=k-1;
m=min(m,res);
}
//有没打开的
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
{
dd(i,j);
dfs(k+1);
dd(i,j); //恢复现场
}
return;
}
int main()
{
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
cin>>a[i][j];
dfs(1);
cout<
和走迷宫很像,只需要起点和终点设置一下,对于是否判断终点都可以
代码1:不判断
#include
#include
#include
#include
using namespace std;
const int N = 1010;
int n, m;
int g[N][N], d[N][N];
int x1,y1,x2,y2;
struct node
{
int x,y;
};
int bfs()
{
queueq;
node tmp;
tmp.x=x1-1;
tmp.y=y1-1;
q.push(tmp);
memset(d, -1, sizeof d);
d[x1-1][y1-1] = 0;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
while (!q.empty())
{
node x=q.front();
q.pop();
for (int i = 0; i < 4; i ++ )
{
int u = x.x + dx[i], v = x.y + dy[i];
tmp.x=u;tmp.y=v;
if (u >= 0 && u < n && v >= 0 && v < n&& g[u][v] == 0 && d[u][v] == -1)
{
d[u][v] = d[x.x][x.y] + 1;
q.push(tmp);
}
}
}
return d[x2-1][y2-1];
}
int main()
{
cin >> n ;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < n; j ++ )
scanf("%1d",&g[i][j]);
cin>>x1>>y1>>x2>>y2;
cout << bfs() << endl;
return 0;
}
代码2:判断
#include
#include
#include
#include
using namespace std;
const int N = 1010;
int n, m;
int g[N][N], d[N][N];
int x1,y1,x2,y2;
struct node
{
int x,y;
};
int bfs()
{
queueq;
node tmp;
tmp.x=x1-1;
tmp.y=y1-1;
q.push(tmp);
memset(d, -1, sizeof d);
d[x1-1][y1-1] = 0;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
while (!q.empty())
{
node x=q.front();
q.pop();
for (int i = 0; i < 4; i ++ )
{
int u = x.x + dx[i], v = x.y + dy[i];
tmp.x=u;tmp.y=v;
if (u >= 0 && u < n && v >= 0 && v < n&& g[u][v] == 0 && d[u][v] == -1)
{
d[u][v] = d[x.x][x.y] + 1;
if(u==x2-1&&v==y2-1)return d[u][v];
q.push(tmp);
}
}
}
}
int main()
{
cin >> n ;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < n; j ++ )
scanf("%1d",&g[i][j]);
cin>>x1>>y1>>x2>>y2;
cout << bfs() << endl;
return 0;
}
刚开始没弄懂题目的意思,原来是象棋里的马走日,所以注意八个方向的实现
代码:bfs
#include
using namespace std;
int dx[8]={-1,-2,-2,-1,1,2,2,1};
int dy[8]={2,1,-1,-2,2,1,-1,-2};//8个方向
int n,m,x,y;
int f[500][500];//存步数
bool vis[500][500];//走没走过
struct node
{
int x,y;
};
void bfs()
{
queue q;
node tmp;
f[x][y]=0;
vis[x][y]=1;
tmp.x=x;
tmp.y=y;
q.push(tmp);
while(!q.empty())
{
int xx=q.front().x,yy=q.front().y;
q.pop();//取队首并出队
for(int i=0;i<8;i++)
{
int u=xx+dx[i],v=yy+dy[i];
tmp.x=u,tmp.y=v;
if(u<1||u>n||v<1||v>m||vis[u][v])continue;//出界或走过就不走
vis[u][v]=1;
q.push(tmp);
f[u][v]=f[xx][yy]+1;
}
}
}
int main()
{
memset(f,-1,sizeof(f));
cin>>n>>m>>x>>y;
bfs();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)printf("%-5d",f[i][j]);
printf("\n");
}
return 0;
}
和马的遍历异曲同工
代码:bfs
#include
using namespace std;
int dx[12]={-1,-2,-2,-1,1,2,2,1,2,2,-2,-2};
int dy[12]={2,1,-1,-2,2,1,-1,-2,-2,2,-2,2};//12个方向
int n,m,x,y;
int f[500][500];//存步数
bool vis[500][500];//走没走过
struct node
{
int x,y;
};
void bfs()
{
queue q;
node tmp;
f[1][1]=0;
vis[1][1]=1;
tmp.x=1;
tmp.y=1;
q.push(tmp);
while(!q.empty())
{
int xx=q.front().x,yy=q.front().y;
q.pop();//取队首并出队
for(int i=0;i<12;i++)
{
int u=xx+dx[i],v=yy+dy[i];
tmp.x=u,tmp.y=v;
if(u<1||u>50||v<1||v>50||vis[u][v])continue;//出界或走过就不走
vis[u][v]=1;
q.push(tmp);
f[u][v]=f[xx][yy]+1;
}
}
}
int main()
{
memset(f,-1,sizeof(f));
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
bfs();
cout<
代码1:dfs
#include
using namespace std;
int n,a,b,res=0x3f3f3f3f;
const int N=210;
int to[N];
bool vis[N];
void dfs(int now,int sum)//now表示当前搜到的楼层,sum表示按钮次数
{
if(now==b) res=min(res,sum);
if(sum>res) return; //注意判断
vis[now]=1;
//不越界并且没有被搜过就搜
if(now+to[now]<=n&&!vis[now+to[now]]) dfs(now+to[now],sum+1);
if(now-to[now]>=1&&!vis[now-to[now]]) dfs(now-to[now],sum+1);
vis[now]=0;//恢复现场
}
int main()
{
cin>>n>>a>>b;
for(int i=1;i<=n;i++) cin>>to[i];
vis[a]=1;
dfs(a,0);
if(res!=0x3f3f3f3f) cout<
代码2:bfs
#include
using namespace std;
int n,a,b,to[205];
bool vis[205];
int now,sum;
struct node
{
int id,step;
}x;//id表示楼层号,step表示按钮次数
void bfs()
{
queue q;
q.push((node){a,0});
while(!q.empty()) //while(q.size())
{
x=q.front();
now=x.id,sum=x.step;
q.pop();
if(now==b) break;
if(now+to[now]<=n&&!vis[now+to[now]])
{
q.push((node){now+to[now],sum+1});
vis[now+to[now]]=1;
}
if(now-to[now]>=1&&!vis[now-to[now]])
{
q.push((node){now-to[now],sum+1});
vis[now-to[now]]=1;
}
}
if(now==b) cout<>n>>a>>b;
for(int i=1;i<=n;i++) cin>>to[i];
bfs();
return 0;
}
代码:bfs
#include
using namespace std;
const int N=1000;
int n,k;
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
int zx[N*2],zy[N*2]; //zx,zy是障碍的坐标
bool s[N+10][N+10],vis[N+10][N+10],flag; //map是地图,vis看是否被访问,flag看是否可以到达
struct node //记录坐标和现在的时间
{
int x,y,t;
};
void bfs(int x,int y,int t)
{
queueq;//STL的queue虽然好打,但是它比手写的队列运行速度要慢的,差别应该也不是很大
node now,net;
now.x=x;now.y=y;now.t=t;
q.push(now);
while(!q.empty())
{
now=q.front(); //取出队头元素
q.pop(); //出队
int a=now.x;
int b=now.y;
int c=now.t;
if(a==n && b==n) //到了终点
{
flag=1; //改变标志
break; //直接退出循环
}
s[zx[now.t-1]][zy[now.t-1]]=1; //要点,障碍降落,因为t是从0开始,所以要减1
for(int i=0;i<4;i++) //枚举四个方向
{
int nx=a+dx[i];
int ny=b+dy[i];
if(nx>=1 && nx<=n && ny>=1 && ny<=n && s[nx][ny]==0 && vis[nx][ny]==0) //在矩阵中,无障碍,无访问
{
net.x=nx;net.y=ny;net.t=c+1; //时间加加
vis[nx][ny]=1;
q.push(net); //进入队列
}
}
}
}
int main()
{
cin>>k;
while(k--)
{
cin>>n;
memset(s,0,sizeof s); //初始化!!
memset(vis,0,sizeof vis);
flag=0; //看是否可以到达终点的标志
for(int i=1;i<=2*n-2;i++) //输入障碍
cin>>zx[i]>>zy[i];
vis[1][1]=1; //起点肯定被访问了
bfs(1,1,0);
if(flag==1)
cout<<"Yes"<
代码1:手打队列,开始只过了两个测试点,请教大佬原来是q数组开小了出现越界,把q数组开的大大大大的(模拟队列)
#include
#include
#include
using namespace std;
typedef pair PII;
const int N = 100;
int a,b,res,n;
int g[N][N],zx,zy;
PII q[4000000];
int bfs()
{
int hh=0,tt=0;
q[0]={1,1};
int dx[2] = {1, 0}, dy[2] = {0, 1};
while (hh<=tt)
{
auto t = q[hh++];
for (int i = 0; i < 2; i ++ )
{
int x = t.first + dx[i], y = t.second + dy[i];
if (x >= 1 && x <= a&& y >= 1 && y <= b&& g[x][y] == 0 )
{
if(x==a&&y==b)
{
res++;
continue;
}
q[++tt]={x, y};
}
}
}
return res;
}
int main()
{
cin >>a>>b;
cin>>n;
memset(g,0,sizeof g);
for (int i = 0; i < n; i ++ )
{
cin>>zx>>zy;
g[zx][zy]=1;
}
cout << bfs() << endl;
return 0;
}
代码2:STL队列
#include
#include
#include
#include
using namespace std;
typedef pair PII;
const int N = 100;
int a,b,n;
long long res;
int g[N][N], d[N][N],zx,zy;
PII q[N*N];
struct node //记录扩展点的坐标信息
{
int x,y;
};
int bfs()
{
queueq; //声明队列
int dx[2] = {1, 0}, dy[2] = {0, 1};//扩展点横坐标的方向右下.扩展点纵坐标的方向右下
node tmp; //中间存扩展点的变量也可以直接打{}
tmp.x=1;
tmp.y=1;
q.push(tmp); //入队
int ans=0;
while(!q.empty()) //当队列不空时
{
node x=q.front(); //取出队列的头
q.pop();//弹出
for (int i = 0; i < 2; i ++ )
{
int u=x.x+dx[i];//更新扩展点的横坐标
int v=x.y+dy[i]; //更新扩展点的纵坐标
tmp.x=u;
tmp.y=v;
if (u >= 1 && u<=a&& v >= 1 && v <= b&& g[u][v] == 0 )
{
if(u==a&&v==b)
{
res++; //如果到达终点方案++
continue; //终点不需要入队,终点不能再继续向下扩展了
}
q.push(tmp);//终点不需要入队,终点不能再继续向下扩展了
}
}
}
return res;
}
int main()
{
cin >>a>>b;
cin>>n;
memset(g,0,sizeof g); //初始化位置,设每个点都可以走
for (int i = 0; i < n; i ++ )
{
cin>>zx>>zy;
g[zx][zy]=1; //初始化位置,设每个点都可以走
}
cout << bfs() << endl;
return 0;
}
代码3:dfs
#include
using namespace std;
int a,b,k,x,y,sum;
bool s[20][20];//地图,初始化为全false,都不能走
void dfs(int x,int y){
if(x==a&&y==b)//到学校了
{
sum++;
return;
}
if(s[x][y+1]) dfs(x,y+1);//如果上面能走,走上面
if(s[x+1][y]) dfs(x+1,y);//如果右面能走,走右面
}
int main()
{
cin>>a>>b;
for(int i=1;i<=a;i++){
for(int j=1;j<=b;j++){
s[i][j]=true;//将地图区域全变为能走的,留一个边界为false
}
}
cin>>k;
while(k--)
{
cin>>x>>y;//输入坐标
s[x][y]=false;//施工不能走(话说这啥路啊,这么多施工的)
}
dfs(1,1);//从1,1开始深搜
cout<
自己打的dfs部分正确(64)
代码:
#include
#include
#include
#include
using namespace std;
const int N = 110;
int n, m, c=6,a1,b1,a2,b2;
int g[N][N], d[N][N];
struct node
{
int x,y;
};
int bfs()
{
queueq;
node tmp;
tmp.x=a1;
tmp.y=b1;
q.push(tmp);
memset(d, -1, sizeof d);
d[a1][b1] = 0;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
while (!q.empty())
{
node x=q.front();
q.pop();
for (int i = 0; i < 4; i ++ )
{
int u = x.x + dx[i], v = x.y + dy[i];
tmp.x=u;tmp.y=v;
if (u >= 0 && u < n && v >= 0 && v < m && g[u][v] != 0 && d[u][v] == -1)
{
d[u][v] = d[x.x][x.y] + 1;
c--;
if(d[u][v]==4)c=6;
q.push(tmp);
}
}
}
return d[a2][b2];
}
int main()
{
cin >> n >> m;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
{
cin >> g[i][j];
if(g[i][j]==2)a1=i,b1=j;
if(g[i][j]==3)a2=i,b2=j;
//cout<<"a1="<=0) cout << bfs() << endl;
else cout<<"-1";
return 0;
}
最优解需要考虑重复走过一个格子的情况
AC代码2:bfs
#include
using namespace std;
struct node //用结构体存储经过一个格子时的状态:当前格子的横纵坐标、步数以及 HP
{
int x,y,step,HP;
};
int n,m;
int a[10][10]; //格子的种类
int vis[10][10]; //经过一个格子时的最大 HP
int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
int flag;
queue q; //广度优先搜索需要的队列
void bfs() //广度优先搜索
{
while(!q.empty())
{
int x=q.front().x,y=q.front().y;
int step=q.front().step,HP=q.front().HP;
q.pop();
if(a[x][y]==3)
{
cout<1) //HP 小于或等于 1 则判定死亡
{
for(int i=0;i<4;i++)
{
int nx=x+dx[i],ny=y+dy[i];
if(a[nx][ny]==1 || a[nx][ny]==3) //尝试扩展的格子是空地或小 H 的家
{
if(vis[nx][ny]>n>>m;
memset(a,-1,sizeof a);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
if(a[i][j]==2)
{
q.push(node{i,j,0,6}); //将出发点入队
}
}
}
bfs();
if(flag==0)puts("-1"); //搜索结束后仍没有到家,判定无解
return 0;
}
暴力出奇迹
代码:
#include
using namespace std;
const int N=1e5+10;
int a,b,n,m,xa[N],ya[N],xb[N],yb[N],res[N];
int main()
{
cin>>n>>m>>a>>b;
for(int i=1;i<=a;i++)cin>>xa[i]>>ya[i];
for(int i=1;i<=b;i++)cin>>xb[i]>>yb[i];
memset(res,127,sizeof(res));
for(int i=1;i<=b;i++)
{
for(int j=1;j<=a;j++)
{
res[i]=min(res[i],abs(xa[j]-xb[i])+abs(ya[j]-yb[i]));
}
cout<