算法小记2 搜索之DFS

今日写完了洛谷上题单内的题,发现自己基本只会写板子,思维能力退化了蛮多,多练习吧。
题单:https://www.luogu.com.cn/training/985963#problems

1.图的遍历

DFS
难度:普及/提高-
洛谷地址:https://www.luogu.com.cn/problem/P3916

思路:

本题相当值得一做,很巧妙的思路。一开始试图正常遍历有向图,但终止条件比较难写,因为要判本来存的答案不能是要访问的节点本身。题解清一色的反向建图,从大节点开始往回推。dfs有两个参数,后一个是记录最大可达节点,由于是大节点回推,所以每个点都能遍历到最优解。同时需要注意用邻接表存二维数组,这样遍历比较省时间。

ac代码:

点击查看代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;

const int N = 1e5 + 5;
int n,m;
vector<int> g[N];
int ans[N]; //ans存已访问过的答案+标记


void dfs(int x,int d){ //d为x最大可达节点
    if(ans[x]) return;
    ans[x]=d;
    for(int i=0;i<g[x].size();i++) dfs(g[x][i],d);
}

signed main() {
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int x,y; cin>>x>>y;
        g[y].push_back(x); //反向建边
    }
    for(int i=n;i>=1;i--) dfs(i,i);
    for(int i=1;i<=n;i++) cout<<ans[i]<<" ";

    return 0;
}

2.八皇后 Checker Challenge

其实是N皇后题
DFS
难度:普及/提高-
洛谷地址:https://www.luogu.com.cn/problem/P1219

思路:

很经典的一道n皇后,按照行dfs,然后一个一个点找可不可行,点的判定需要注意,用三个数组分别存列和两个主对角线,注意对角线的判定是平行。最后记得回溯即可。

ac代码:

点击查看代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;

const int N = 30;
int n,cnt;
int col[N],d1[N],d2[N],ans[N];

void dfs(int x){ //行
    if(x==n+1){
        cnt++;
        if(cnt<=3){
            for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
            cout<<endl;
        }
        return;
    }
    for(int i=1;i<=n;i++){ //列
        if(col[i]||d1[x-i+n]||d2[x+i]) continue;
//        cout<<x<<" "<<i<<endl;
        ans[x]=i;
        col[i]=d1[x-i+n]=d2[x+i]=1;
        dfs(x+1);
        ans[x]=0;
        col[i]=d1[x-i+n]=d2[x+i]=0;
    }
}


signed main() {
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n;
    dfs(1);
    cout<<cnt;
    
    return 0;
}

3.Lake Counting S

DFS/BFS
难度:普及-
洛谷地址:https://www.luogu.com.cn/problem/P1596

思路:

本题没什么思维量,需要注意的就是主函数需要遍历每个点,以加到所有连通块。题解有个可以简化空间的方法就是不用vis数组,把遍历过的'W'改成'.'即可。

ac代码:

点击查看代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;

const int dx[]={-1,1,0,0,1,1,-1,-1},dy[]={0,0,1,-1,1,-1,1,-1};
int n,m,cnt;
int vis[105][105];
char s[105][105];

void dfs(int x,int y){
    if(s[x][y]=='.') return;
    vis[x][y]=1;
    for(int k=0;k<8;k++){
        int nx=x+dx[k],ny=y+dy[k];
        if(nx<1||nx>n||ny<1||ny>m||vis[nx][ny]) continue;
        dfs(nx,ny);
    }
}

signed main() {
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>s[i]+1;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(s[i][j]=='W'&&!vis[i][j]){
                dfs(i,j); cnt++;
            }
        }
    }
    cout<<cnt;
    return 0;
}

4.滑雪

记忆化搜索(DP+DFS)
难度:普及/提高-
洛谷地址:https://www.luogu.com.cn/problem/P1434

思路:

非常好题。第一遍写的代码基本上就是暴搜,于是喜提超时。没想到什么优化解法,遂去看了解析,发现是记忆化搜索,即DP+DFS。一开始我以为先算下一步最长路会影响正确结果,毕竟很可能需要加上dfs的值,然后发现是先算最底端的最长路、在回溯过程中更新最长路的一个dp过程。

ac代码:

点击查看代码
// 记忆化搜索
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;

const int N = 105;
const int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
int n,m,mn,cnt=1,ans;
int mp[N][N],f[N][N];

int dfs(int x,int y){
    if(f[x][y]) return f[x][y]; //记忆化搜索
    f[x][y]=1; //初始化
    for(int k=0;k<4;k++){
        int nx=x+dx[k],ny=y+dy[k];
        if(nx<1||nx>n||ny<1||ny>m||mp[nx][ny]>=mp[x][y]) continue;
        dfs(nx,ny); //先算下一步最长路
        f[x][y]=max(f[x][y],f[nx][ny]+1); //回溯过程中才更新这一步最长路
    }
    return f[x][y];
}

signed main() {
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>mp[i][j];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            ans=max(ans,dfs(i,j));
            
    cout<<ans;
    
    return 0;
}
posted @ 2026-04-03 20:40  whisper-rrr  阅读(4)  评论(0)    收藏  举报