目前结论
目前结论就是: 极大连通子图用dfs好点,还有棋盘问题,八皇后,搜索全部的解 ,求最远路径,如156:LETTERS
求最短路径bfs合适点,遇到的第一个解就是最优解
BFS是向(能走的方向拓展),第一次拓展到达终点时,这条路就是起点到终点的最短路径,
DFS是从起始点出发往深处走,能走多深走多深,可以分开每一条道路并比较所有的路的情况
BFS虽然很快找到离终点最近的路,但也许题目所求的未必是直接这条路,而是满足条件的结果,比如 鸣人与佐助那题,虽然找到到终点最短的路,但未必是查克拉消耗最少的路。也就是,题目要求的不一定是路径最短,而是另一个量的最值。
156:LETTERS(dfs求最长路径)
156:LETTERS
一开始读错了题意,以为像算水坑个数(求最大连通子图的个数)那道题,求一个水坑的水洼数目。
正解是:一条路上能走过的不同字母
这道题DFS就很适用了,求一条路上的情况
DFS就可以比较不同的道路上的情况
但据说DFS能解决的BFS都可以,但我BFS还没解出来(4分
#include<bits/stdc++.h>
using namespace std;
char a[25][25];
int vis[26];//a[0]代表A被到达过几次
int viss[25][25];
//int dx[8]={1,-1,0,0,-1,1,-1,1};
//int dy[8]={0,0,-1,1,-1,-1,1,1};
int dx[4]={1,-1,0,0};
int dy[4]={0,0,-1,1};
int m,n;
bool inside(int cx,int cy){
return (cx>=0&&cx<m&&cy>=0&&cy<n);
}
void init(){
memset(vis,0,sizeof(vis));
memset(viss,0,sizeof(viss));
}
int maxx=0;
void dfs(int x,int y,int step){
// cnt++;
maxx=max(step,maxx);
for(int i=0;i<4;i++){
int cx=x+dx[i];
int cy=y+dy[i];
if(inside(cx,cy)&&!viss[cx][cy]&&!vis[a[cx][cy]-'A']){
viss[cx][cy]=1;
vis[a[cx][cy]-'A']++;
dfs(cx,cy,step+1);
viss[cx][cy]=0;
vis[a[cx][cy]-'A']--;
}
}
}
int main(){//同一个字母不能访问两次
ios_base::sync_with_stdio(0);
cin>>m>>n;
for(int i=0;i<m;i++){
for(int j =0;j<n;j++){
cin>>a[i][j];
}
}
init();
vis[a[0][0]-'A']=1;
viss[0][0]=1;
dfs(0,0,1);
cout<<maxx;
return 0;
}
BFS(只有4分)how to do?
#include<bits/stdc++.h>
using namespace std;
char a[25][25];
int vis[26];//a[0]代表A被到达过几次
int viss[25][25];
//int dx[8]={1,-1,0,0,-1,1,-1,1};
//int dy[8]={0,0,-1,1,-1,-1,1,1};
int dx[4]={1,-1,0,0};
int dy[4]={0,0,-1,1};
int m,n;
bool inside(int cx,int cy){
return (cx>=0&&cx<m&&cy>=0&&cy<n);
}
void init(){
memset(vis,0,sizeof(vis));
}
struct node{
int x;
int y;
node(int xx,int yy):x(xx),y(yy){}
};
queue<node> Q;
int cnt=0;
void bfs(){
while(!Q.empty()){
node p=Q.front();Q.pop();
cnt++;
int x=p.x;
int y=p.y;
for(int i=0;i<4;i++){
int cx=x+dx[i];
int cy=y+dy[i];
char ch=a[cx][cy];
if(inside(cx,cy)&&!viss[cx][cy]&&vis[ch-'A']==0){
Q.push(node(cx,cy));
vis[ch-'A']=1;
viss[cx][cy]=1;
bfs();//加上这条五分
}
}
}
}
int main(){//同一个字母不能访问两次
ios_base::sync_with_stdio(0);
cin>>m>>n;
for(int i=0;i<m;i++){
for(int j =0;j<n;j++){
cin>>a[i][j];
}
}
init();
Q.push(node(0,0));
vis[a[0][0]-'A']=1;
viss[0][0]=1;
bfs();
cout<<cnt;
return 0;
}
166:The Castle城堡问题(联通子集个数、大小)
传送门
求极大连通子图,
据说dfs能解决的bfs都能解,那这题用bfs怎么解呢?
#include<bits/stdc++.h>
using namespace std;
int a[55][55];
int vis[55][55];
int m,n;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int maxx=-1;
bool inside(int cx,int cy){
return (cx>=0&&cx<m&&cy>=0&&cy<n);
}
void init(){
memset(vis,0,sizeof(vis));
memset(a,0,sizeof(a));
}
int room;//房间数
int space;//最大的房间多大,比较每个房间的space取max
void dfs(int x,int y){
if(vis[x][y])return;
else{
space++;
vis[x][y]=1;
}
int state=a[x][y];
int cx=-1;
int cy=-1;
if(!(state&1)){//西面没墙
if(inside(x,y-1)&&!vis[x][y-1]){
cx=x;
cy=y-1;
dfs(cx,cy);
}
}
if(!(state&2)){//北面没墙
if(inside(x-1,y)&&!vis[x-1][y]){
cx=x-1;
cy=y;
dfs(cx,cy);
}
}
if(!(state&4)){//东面没墙
if(inside(x,y+1)&&!vis[x][y+1]){
cx=x;
cy=y+1;
dfs(cx,cy);
}
}
if(!(state&8)){//南面没墙
if(inside(x+1,y)&&!vis[x+1][y]){
cx=x+1;
cy=y;
dfs(cx,cy);
}
}
if(cx==-1&&cy==-1){
maxx=max(maxx,space);
return ;
}
}
int main(){//同一个字母不能访问两次
ios_base::sync_with_stdio(0);
cin>>m>>n;
init();
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
cin>>a[i][j];
}
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(!vis[i][j]){
space=0;
room++;//存放房间数
dfs(i,j);
}
}
}
cout<<room<<endl;
cout<<maxx<<endl;
return 0;
}
又重新做了一遍
#include<iostream>
#include <algorithm>
using namespace std;
const int N=55;
int m,n;
int vis[N][N];
int a[N][N];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
bool inside(int x,int y){
if(x>=0&&x<m&&y>=0&&y<n)return true;
else return false;
}
int maxx=-1;
int step;
void dfs(int x,int y){
maxx=max(maxx,step);
int v=a[x][y];
if(!(v&1)&&inside(x,y-1)&&!vis[x][y-1]){
vis[x][y-1]=1;
step++;
dfs(x,y-1);//下一条路不能走这一点了
}
if(!(v&2)&&inside(x-1,y)&&!vis[x-1][y]){
vis[x-1][y]=1;
step++;
dfs(x-1,y);
}
if(!(v&4)&&inside(x,y+1)&&!vis[x][y+1]){
vis[x][y+1]=1;
step++;
dfs(x,y+1);
}
if(!(v&8)&&inside(x+1,y)&&!vis[x+1][y]){
vis[x+1][y]=1;
step++;
dfs(x+1,y);
}
}
int main() {//56
cin>>m>>n;
int cnt=0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
cin>>a[i][j];
}
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(!vis[i][j]) {
vis[i][j]=1;
step=1;//step,一个房间的大小
cnt++;//房间数量
dfs(i,j);
}
}
}
cout<<cnt<<endl<<maxx;
return 0;
}
//求最大联通子集,其中所有元素不一定能一条路踏遍2,一笔画
1388:Lake Counting(联通子集个数)
#include<iostream>
#include <algorithm>
using namespace std;
const int N=105;
int m,n;
int vis[N][N];
char a[N][N];
int dx[8]={1,-1,0,0,1,1,-1,-1};
int dy[8]={0,0,1,-1,1,-1,-1,1};
bool inside(int x,int y){
if(x>=0&&x<m&&y>=0&&y<n)return true;
else return false;
}
void dfs(int x,int y){
for(int i=0;i<8;i++){
int cx=x+dx[i];
int cy=y+dy[i];
if(inside(cx,cy)&&!vis[cx][cy]&&a[cx][cy]=='W'){
vis[cx][cy]=1;
dfs(cx,cy);
}
}
}
int main() {//36
cin>>m>>n;
int cnt=0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
cin>>a[i][j];
}
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(a[i][j]=='W'&&!vis[i][j]) {
vis[i][j]=1;
// step=1;//step,一个联通子集的大小
cnt++;//联通子集数量
dfs(i,j);
}
}
}
cout<<cnt;
return 0;
}
//求最大联通子集,其中所有元素不一定能一条路踏遍2,一笔画