首页 > 编程语言 >2024算法基础公选课练习五(DFS2)

2024算法基础公选课练习五(DFS2)

时间:2024-11-26 17:03:12浏览次数:11  
标签:std return 选课 int vis cin 2024 DFS2 vector

一、前言

因为此次题目较多,我也不想分成两篇博客来发,我就直接给代码了,如果题目有需要强调的地方再特殊说明

二、题目总览

三、具体题目

3.1 问题 A: 勘探油田

我的代码

8方向的flood fill模型

#include <bits/stdc++.h>
using i64 = long long;
constexpr int N = 1e2+5,M = 1e6+5,INF = 0x3f3f3f3f;
int ans;
struct Node{
	int _x,_y;
};
int n,m;
int dx[] = {0,1,1,1,0,-1,-1,-1};
int dy[] = {1,1,0,-1,-1,-1,0,1};
std::vector<std::vector<char>> g(N,std::vector<char>(N));
std::vector<std::vector<bool>> vis(N,std::vector<bool>(N,false));
void bfs(int x,int y){
	std::queue<Node> q;
	Node t;
	t._x = x,t._y = y;
	q.emplace(t);
	vis[x][y] = true;
	++ans;
	while(!q.empty()){
		auto t = q.front();
		q.pop();
		for(int i = 0;i<8;++i){
			int u = t._x+dx[i],v = t._y+dy[i];
			if(u<1||u>n||v<1||v>m||vis[u][v]||g[u][v]=='*') continue;
			vis[u][v] = true;
			Node t1;
			t1._x = u,t1._y = v;
			q.emplace(t1);
		}
	}
}
void solve(){
	
	while(std::cin >> n >> m){
		if(n==0&&m==0) break;
		vis.assign(N,std::vector<bool>(N,false));
		for(int i = 1;i<=n;++i){
			for(int j = 1;j<=m;++j){
				std::cin >> g[i][j];
			}
		}
		ans = 0;
		for(int i = 1;i<=n;++i){
			for(int j = 1;j<=m;++j){
				if(g[i][j]=='@'&&!vis[i][j]){
					bfs(i,j);
				}
			}
		}
		std::cout << ans << '\n';
	}
}
int main(){
	std::cin.tie(nullptr)->sync_with_stdio(false);
	
	int t = 1;
//	std::cin >> t;
	while(t--){
		solve();
	}
	
	return 0;
}

3.2 问题 B: 景区旅游

我的代码

一次dfs即可

#include <bits/stdc++.h>
using i64 = long long;
constexpr int N = 15,INF = 0x3f3f3f3f;
int n,m;
std::vector<std::vector<char>> g(N,std::vector<char>(N));
std::vector<std::vector<bool>> vis(N,std::vector<bool>(N,false));
int dx[] = {1,-1,0,0};
int dy[] = {0,0,1,-1};
int ans1 = 0,ans2 = INF;
struct node{
	int _x,_y,_s;
}t,t1;
int sx,sy,ex,ey;
std::queue<node> q; 

void dfs(int u,int x,int y){
	if(x==ex&&y==ey){
		ans1 = std::max(ans1,u);
		ans2 = std::min(ans2,u);
		return;
	}
	for(int i = 0;i<4;++i){
		int x1 = x+dx[i],y1 = y+dy[i];
		if(x1<1||x1>n||y1<1||y1>m||vis[x1][y1]||g[x1][y1]=='0') continue;
		vis[x1][y1] = true;
		dfs(u+1,x1,y1);
		vis[x1][y1] = false;
	}
}

int main(){
	std::cin.tie(nullptr)->sync_with_stdio(false);
	
	std::cin >> n >> m;
	for(int i = 1;i<=n;i++){
		for(int j = 1;j<=m;j++){
			std::cin >> g[i][j];
			if(g[i][j]=='S'){
				sx=i,sy=j;
			}else if(g[i][j]=='E'){
				ex=i,ey=j;
			}
		}
	}
	vis[sx][sy] = true;
	dfs(0,sx,sy);
	std::cout << ans1 << ' ' << ans2 << '\n';
	
	return 0;
}

3.3 问题 C: 搜索与回溯——迷宫问题

我的代码

#include <bits/stdc++.h>
using i64 = long long;
constexpr int N = 15,M = 1e6+5,INF = 0x3f3f3f3f;
int g[N][N];
bool vis[N][N];
int dx[] = {0,1,1,1,0,-1,-1,-1};
int dy[] = {1,1,0,-1,-1,-1,0,1};
int n;
int sx,sy,ex,ey,ans;
void dfs(int x,int y){
	if(x==ex&&y==ey){
		++ans;
		return;
	}
	for(int i = 0;i<8;++i){
		int u = x+dx[i],v = y+dy[i];
		if(u<1||u>n||v<1||v>n||vis[u][v]||g[u][v]==1) continue;
		vis[u][v] = true;
		dfs(u,v);
		vis[u][v] = false;
	}
}
void solve(){
	std::cin >> n;
	for(int i = 1;i<=n;++i){
		for(int j = 1;j<=n;++j){
			std::cin >> g[i][j];
		}
	}
	sx = 1,sy = 1,ex = 1,ey = n;
	vis[sx][sy] = true;
	dfs(sx,sy);
	std::cout << ans << '\n';
}
int main(){
	std::cin.tie(nullptr)->sync_with_stdio(false);
	
	int t = 1;
//	std::cin >> t;
	while(t--){
		solve();
	}
	
	return 0;
}

3.4 问题 D: 搜索——魔法卷轴

我的代码

dfs的时候需要多加一个列是否已经有手印的判断

#include <bits/stdc++.h>
using i64 = long long;
int n,m,res;
char a[15][15];
bool b[15];
void dfs(int k,int s){
    if(s>=m){
        res+=1;
        return;
    }
    if(k>n){
        return;
    }
    for(int i=1;i<=n;i++){
        if(a[k][i] == '@' && b[i]==0){
            b[i]=1;
            dfs(k+1,s+1);
            b[i]=0;
        }
    }
    dfs(k+1,s);
}
int main(){
    std::cin.tie(nullptr)->sync_with_stdio(false);
    std::cin>>n>>m;
    for (int i=1;i<=n;i++){
        for (int j=1;j<=n;j++){
            std::cin>>a[i][j];
        }
    }
    res=0;
    dfs(1,0);
    std::cout << res<< '\n';
    return 0;
}

3.5 问题 E: 搜索与回溯——N 皇后问题

我的代码

经典dfs

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N = 20;
int n;
char graph[N][N];
bitset<N> col,dg,adg;//column,diagonal,against the diagonal line
void dfs(int dep){
    if(dep==n){
		for(int i = 0;i<n;i++){
			for(int j = 0;j<n;j++){
				if(graph[i][j]=='Q'){
					cout << j+1 << " \n"[i==n-1];
					break;
				}
			}
		}
        return;
    }
    for(int i = 0;i<n;i++){
        if(!col[i]&&!dg[dep+i]&&!adg[n+i-dep]){
            col[i]=dg[dep+i]=adg[n+i-dep]=1;
            graph[dep][i]='Q';
            dfs(dep+1);
            col[i]=dg[dep+i]=adg[n+i-dep]=0;
            graph[dep][i]='.';
        }
    }
}
void solve(){
    cin >> n;
    for(int i = 0;i<n;i++) for(int j = 0;j<n;j++) graph[i][j]='.';
    
	if(n!=3) dfs(0);
	else{
		cout << "no solute!\n";
	}
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int T = 1;
    // cin >> T;
    while(T--){
        solve();
    }
    return 0;
}

3.6 问题 F: 搜索与回溯——工作分配问题

我的代码

使用next_permutation生成全排列暴力枚举

#include <bits/stdc++.h>
using i64 = long long;
constexpr int N = 1e5+5,M = 1e6+5,INF = 0x3f3f3f3f;
int c[25][25];
int n,ans = INF;
void solve(){
	std::cin >> n;
	for(int i = 1;i<=n;++i) for(int j = 1;j<=n;++j) std::cin >> c[i][j];
	std::vector<int> v(n,0);
	std::iota(v.begin(),v.end(),1);
	do{
		int sum = 0;
		for(int i = 1;i<=n;++i){
			sum+=c[i][v[i-1]];
		}
		ans = std::min(ans,sum);
	}while(std::next_permutation(v.begin(),v.end()));
	std::cout << ans << '\n';
}
int main(){
	std::cin.tie(nullptr)->sync_with_stdio(false);
	
	int t = 1;
//	std::cin >> t;
	while(t--){
		solve();
	}
	
	return 0;
}

3.7 问题 G: 观星

我的代码

题目讲得有点模糊,不过分析一下样例应该就能明白

#include <bits/stdc++.h>
using i64 = long long;
constexpr int N = 1505,M = 1e6+5,INF = 0x3f3f3f3f;
int n,m;
struct Node{
	int x,y;
}t,t1;
int dx[] = {0,1,1,1,0,-1,-1,-1};
int dy[] = {1,1,0,-1,-1,-1,0,1};
char g[N][N];
bool vis[N][N];
int cnt=0,maxn=-1;
struct xingzuo{
	int sx,sy,cnt;
};
std::vector<xingzuo> ans;
void bfs(int sx,int sy){
	std::queue<Node> q;
	t.x = sx,t.y = sy;
	q.emplace(t);
	vis[sx][sy] = true;
	int cnt_ = 0;
	while(!q.empty()){
		auto t = q.front();
		q.pop();
		++cnt_;
		for(int i = 0;i<8;++i){
			int u = t.x+dx[i],v = t.y+dy[i];
			if(u<1||u>n||v<1||v>m||vis[u][v]||g[u][v]=='.') continue;
			vis[u][v] = true;
			t1.x = u,t1.y = v;
			q.emplace(t1);
		}
	}
	xingzuo tmp;
	tmp.sx = sx,tmp.sy = sy,tmp.cnt = cnt_;
	ans.emplace_back(tmp);
}
void solve(){
	std::cin >> n >> m;
	for(int i = 1;i<=n;++i){
		for(int j = 1;j<=m;++j){
			std::cin >> g[i][j];
		}
	}
	for(int i = 1;i<=n;++i){
		for(int j = 1;j<=m;++j){
			if(g[i][j]=='*'&&!vis[i][j]){
				++cnt;
				bfs(i,j);
			}
		}
	}
	std::set<int> set;
	std::map<int,int> map;
	int res = 0;
	for(const auto &ansi:ans){
		set.insert(ansi.cnt);
		map[ansi.cnt]++;
	}
	for(const auto &mpi:map){
		res = std::max(res,mpi.first*mpi.second);
	}
	std::cout << set.size() << ' ' << res << '\n';
}
int main(){
	std::cin.tie(nullptr)->sync_with_stdio(false);
	
	int t = 1;
//	std::cin >> t;
	while(t--){
		solve();
	}
	
	return 0;
}

3.8 问题 H: 搜索与回溯——字符序列

我的代码

#include <bits/stdc++.h>
using i64 = long long;
std::vector<char> s(15);
int n,ans;
void dfs(int u) {
    if(u==n+1) {
        ++ans;
        return;
    }
    for(char c = 'A';c<='C';++c) {
        s[u] = c;
        if(u==1||s[u]!=s[u-2]||s[u-1]!=s[u-3]) {
            dfs(u+1);
        }else {
            s[u] = 0;
        }
    }
}
 
int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
 
    std::cin >> n;
    dfs(1);
    std::cout << ans << '\n';
 
    return 0;
}

3.9 问题 I: 图的m着色问题(N26)

我的代码

#include<bits/stdc++.h>
using namespace std;
constexpr int N = 1e4+5,M = 1e3+5;
int n,k,m,a[N],b[M][M],ans;
bool check(int s){
    for(int i=1;i<=s;i++){
    	if(b[i][s]&&a[i]==a[s]){
    		return false;
		}
	}
    return true;
}
void dfs(int s){
    if(s>n){
        ++ans;
        return;
    }
    for(int i=1;i<=m;i++){
        a[s]=i;
        if(check(s)) dfs(s+1);
        else a[s]=0;
    }
}
int main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    
	int T = 1;cin >> T;
    while(T--){
        memset(b,0,sizeof b);
        memset(a,0,sizeof a);
        ans = 0;
        cin>>n>>k>>m;
        while(k--){
        	int x,y;
        	cin >> x >> y;
			b[x][y] = 1;
		}
        dfs(1);
        cout << ans << '\n';
    }
    
    return 0;
}

3.10 问题 J: 搜索与回溯——部落卫队

我的代码

参考了另外一篇博客的写法

#include<cstdio>
#include<cstring>
struct vellager{
    int other[105],s;
} vec[105];
int m,n,send;
bool can[105],use[105],end[105];
void flag(int x,int tot){
    if(x>n){
        if(tot>send){
            send=tot;
            memcpy(end,use,n+1);
        }
        return;
    }
    if(!can[x] && !use[x]){
        use[x]=true;
        bool now[105];
        memcpy(now,can,n+1);
        for(int j=0;j<vec[x].s;j++) can[vec[x].other[j]]=true;
        flag(x+1,tot+1);
        use[x]=false;
        memcpy(can,now,n+1);
    }
    flag(x+1,tot);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++){
        int x,y;scanf("%d%d",&x,&y);
        if(!vec[x].other[0]) vec[x].s=0;
        if(!vec[y].other[0]) vec[y].s=0;
        vec[x].other[vec[x].s++]=y;
        vec[y].other[vec[y].s++]=x;
    }
    flag(1,0);
    printf("%d\n",send);
    for(int i=1;i<=n;i++) i-1?printf(" %d",end[i]):printf("%d",end[i]);
    return 0;
}

3.11 问题 K: 植物大战僵尸现实版

我的代码

第二次出现这个题了,老师把数据范围改正确了x和y都介于1到1e9之间

思路还是dfs枚举行的状态,然后贪心判断列是否修改,最后答案取max即可

#include <bits/stdc++.h>
using i64 = long long;
constexpr int N = 1e5+5,M = 1e6+5,INF = 0x3f3f3f3f;
std::vector<std::vector<i64>> g(15,std::vector<i64>(205,0));
std::vector<std::vector<i64>> tmp(15,std::vector<i64>(205,0));
std::vector<int> v(15,0);
std::vector<i64> pre(205,0);
i64 n,m,x,t;
i64 ans=0;
void dfs(int u){
	if(u==n+1){
		i64 cnt = 0;
		for(int i = 1;i<=n;++i) cnt+=v[i]?1:0;
		if(cnt>t) return;
		std::copy(tmp.begin(),tmp.end(),g.begin());
		pre.assign(205,0);
		for(int i = 1;i<=n;++i){
			for(int j = 1;j<=m;++j){
				g[i][j] = v[i]?x:g[i][j];
			}
		}
		for(int i = 1;i<=m;++i){
			for(int j = 1;j<=n;++j){
				pre[i]+=g[j][i];
			}
		}
		i64 sum = 0;
		std::sort(pre.begin()+1,pre.begin()+1+m);
		for(int i = 1;i<=m;++i){
			if(cnt<t&&pre[i]<x*n){
				sum+=x*n;
				++cnt;
			}else{
				sum+=pre[i];
			}
		}
		ans = std::max(ans,sum);
		return;
	}
	v[u] = 0;
	dfs(u+1);
	v[u] = 1;
	dfs(u+1);
}
void solve(){
	std::cin >> n >> m >> x >> t;
	for(int i = 1;i<=n;++i){
		for(int j = 1;j<=m;++j){
			std::cin >> g[i][j];
		}
	}
	std::copy(g.begin(),g.end(),tmp.begin());
	dfs(1);
	std::cout << ans << '\n';
}
int main(){
	std::cin.tie(nullptr)->sync_with_stdio(false);
	
	int t = 1;
//	std::cin >> t;
	while(t--){
		solve();
	}
	
	return 0;
}

3.12 问题 L: 袜子配对

我的代码

思路同牛客小白月赛105的D题,跳转链接

#include <bits/stdc++.h>
using i64 = long long;
constexpr int N = 2e5+5;

int n,m,k;
std::vector<int> colors(N,0);

struct DSU {
    int _n;
    std::vector<int> _fa,_size;
    DSU(){}
    DSU(int n){
        init(n);
    }
    void init(int n) {
        _fa.resize(n);
        std::iota(_fa.begin(),_fa.end(),0);
        _size.assign(n,1);
    }
    int find(int x) {
        if(x!=_fa[x]) {
            _fa[x] = find(_fa[x]);
        }
        return _fa[x];
    }
    bool same(int x,int y) {
        return find(x)==find(y);
    }
    bool merge(int x,int y) {
        int fx = find(x);
        int fy = find(y);
        if(fx!=fy) {
            _size[fx]+=_size[fy];
            _fa[fy] = fx;
            return true;
        }
        return false;
    }
};
int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    std::cin >> n >> m >> k;
    DSU dsu(N);
    for(int i = 1;i<=n;++i) {
        std::cin >> colors[i];
    }
    int ans = 0;
    while(m--) {
        int l,r;std::cin >> l >> r;
        if(dsu.merge(colors[l],colors[r])) {
            ++ans;
        }
    }
    std::cout << ans << '\n';
    
    return 0;
}

3.13 问题 M: 素数树

我的代码

突然发现自己代码逻辑错了,但是仍然能AC,说明后台测试点的数据不够刁钻,等我修改一下后续再把代码放上来

正确的思路应该是判断该树是否为二叉树,如果是的话,那么只需要对相邻的边依次输出2和3即可;如果不是的话,输出-1然后return处理下一组即可

标签:std,return,选课,int,vis,cin,2024,DFS2,vector
From: https://blog.csdn.net/Beau_Will/article/details/144062014

相关文章

  • ChatGPT国内中文版镜像网站整理合集(2024/11/27更新)
    一、GPT中文镜像站①yixiaai.com  支持GPT4、4o以及o1,支持MJ绘画 AIChat什么是镜像站镜像站(MirrorSite)是指通过复制原始网站内容和结构,创建的备用网站。其主要目的是在原始网站无法访问时,提供相同或类似的服务和信息。ChatGPT镜像站的用途绕过访问限制:在某些地区......
  • ICPC南京2024
    C.Topology考虑没有限制怎么做,对于每个点分配$$(siz_x-1)!\prod\frac{1}{siz_v!}$$转化为子问题乘起来即可如果\(k\)要放在\(k\),我们从下往上放,对于\(k\)的子树先乘上\(\C_{n-i}^{siz_x}\),接着乘上子树对应的系数,使k的子树全都确定了对于父节点\(f\)放在p......
  • 2024.11.26模拟赛
    昨天也打了模拟赛。但没补没总结。为什么呢。因为懒。今天来了之后先犯困了一个坤小时。犯困的那两个半小时属于是连暴力都没法想怎么去写的那种。好不容易慢慢清醒了,又不想写了。随便打了个T3的暴力,又写了个T1的爆搜,结果爆搜炸了。所以,今天昨天打的都很不怎么样。结果考完之后......
  • [2024.11.26]NOIP模拟赛
    挂分+不会+暴力场。赛时T1看到大样例里面的输出后意识到这题需要高精。乘法高精讲的时候没听,但是后来不知道从哪看到这就是所谓的加法卷积,所以直接按照卷积的形式写就行了。然后开始看题,感觉特别像打表找规律。看着样例觉得是蛇形填充,写完以后自己造了个样例发现随便组合都......
  • 【R安装】R语言的详细安装及环境配置(2024年11月)
    目录R及Rstudio下载R下载Rstudio下载R及Rstudio安装R安装Rtools安装Rstudio安装运行RStudio通过RStudio配置使用特定的R版本参考R及Rstudio下载R下载R官网-TheRProjectforStatisticalComputing点击【downloadR】,进入下载界面:选择需要的镜像版本,如下:......
  • 985研一学习日记 - 2024.11.25
    一个人内耗,说明他活在过去;一个人焦虑,说明他活在未来。只有当一个人平静时,他才活在现在。日常1、起床2、健身3、LeetCode刷了1题单词拆分给定一个非空字符串s和一个包含非空单词的列表wordDict,判定s是否可以被空格拆分为一个或多个在字典中出现的单词。该问题......
  • 网络安全(黑客技术)2024年三个月自学手册
    ......
  • 网络安全(黑客技术)2024年三个月自学手册
    ......
  • 自学网络安全(黑客技术)2024年 —100天学习计划
    ......
  • 自学网络安全(黑客技术)2024年 —100天学习计划
    ......