c++专题五

news/2025/2/13 20:23:42/文章来源:https://www.cnblogs.com/sssyyyqqq/p/18714367

C++专题五学习(深度算法)

深度优先探索(DFS)

适用全排列问题等需要列举出全部情况的 (配合递归

大致模版:

void dfs(...){if(递归结束条件){...;	//计入答案return;}for(int i=0;i<n;i++){	//有的有循环有的没有if(需要满足的条件){...;dfs(...+1);撤销;	 //比如前面++,这里就--}}
}
int main(){...;dfs(开始的位置);...;
}

例1:洛谷p1219八皇后

每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

Input

一行一个正整数 n,表示棋盘是 n×n大小的。

Output

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

#include<bits/stdc++.h>
using namespace std;
const int N=14;
int y[N],d1[2*N],d2[2*N];
vector<int> v;
vector<vector<int>> ans;int n;
void dfs(int i){ 	//一行一行放if(i>n){ans.push_back(v);return;}for(int j=1;j<=n;j++){if(y[j]==0&&d1[i-j+n]==0&&d2[i+j]==0){y[j]++;d1[i-j+n]++;d2[i+j]++;v.push_back(j);dfs(i+1);//撤销v.pop_back();y[j]--;d1[i-j+n]--;d2[i+j]--;}}
}
int main(){cin>>n;dfs(1);sort(ans.begin(),ans.end());for(int i=0;i<3;i++){      //输出for(const auto& el: ans[i]){cout<<el<<" ";}cout<<endl;}cout<<ans.size()<<endl;return 0;
}

例2:洛谷p2404自然数拆分问题

sample

Input

7

Output

1+1+1+1+1+1+1
1+1+1+1+1+2
1+1+1+1+3
1+1+1+2+2
1+1+1+4
1+1+2+3
1+1+5
1+2+2+2
1+2+4
1+3+3
1+6
2+2+3
2+5
3+4
#include<bits/stdc++.h>
using namespace std;
int n,t=0,a[10000];
void dfs(int cur,int sum){  //从cur开始拆,防止重复if(sum==0){cout<<a[0];for(int i=1;i<t;i++){cout<<"+"<<a[i];}cout<<endl;return ;}if(cur>sum||cur==n)return ;a[t++]=cur;dfs(cur,sum-cur);t--;dfs(cur+1,sum);
}
int main(){cin>>n;dfs(1,n);return 0;
}

广度优先探索(BFS)

适用于需要求最值的,或需要求板块之类的(配合队列

大致模版:

...
//四维方向
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
//或者八维
int dx[]={0,0,1,-1,1,1,-1,-1};
int dy[]={1,-1,0,0,-1,1,-1,1};
bool vis[N][N];  //标记(害怕重复选到的需要标记,如果没有这个问题就不需要)
void bfs(int sx,int sy){...;queue<pair<int,int>> q;vis[sx][sy]=true;q.push({sx,sy});while(!q.empty()){int x=q.front().first;int y=q.front().second;q.pop();for(int i=0;i<4(或者是8);i++){int nx=x+dx[i];int ny=y+dy[i];if(nx和ny没有超出边界且符合条件){...; // 计入答案q.push({nx,ny});}}}
}
int main(){...;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(!vis[i][j]){bfs(i,j);}}}			//或者直接从头开始探索...;
}

例1:洛谷p1162填涂颜色

被1包围的0要被填上2。

sample

Input

6
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1

Output

0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1

#include<bits/stdc++.h>
using namespace std;
int n;
int a[31][31],b[31][31],t;
struct xy{int x,y;
};
queue<xy> q;
int fx[4]={-1,1,0,0};
int fy[4]={0,0,-1,1};
int main(){cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cin>>t;if(t==1) a[i][j]=1;}}b[0][0]=1;q.push(xy{0,0});while(!q.empty()){xy p=q.front();q.pop();for(int i=0;i<4;i++){int x=p.x+fx[i];int y=p.y+fy[i];if(x<0||x>n+1||y<0||y>n+1) continue;if(a[x][y]==0&&b[x][y]==0){b[x][y]=1;q.push(xy{x,y});}}}for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(a[i][j]==0&&b[i][j]==0)cout<<"2"<<" "; // b[i][j]是标签,没被打上标签的0可以变为2else if(a[i][j]==1)cout<<"1"<<" ";else cout<<"0"<<" ";}cout<<endl;}	return 0;
}

例2:洛谷p3456山峰山谷

比周围的一片高的那块是山峰,比周围一片矮的是山谷,整片一样高的既是山峰又是山谷,输出山峰,山谷数量

#include<bits/stdc++.h>
using namespace std;
const int N=1000+5;int dx[]={0,0,1,-1,1,1,-1,-1};
int dy[]={1,-1,0,0,-1,1,-1,1};
int n,a[N][N];int cntr,cntv;
bool vis[N][N];
void bfs(int sx,int sy){bool is_r=true;bool is_v=true;queue<pair<int,int>> q;vis[sx][sy]=true;q.push({sx,sy});while(!q.empty()){int x=q.front().first;int y=q.front().second;q.pop();for(int i=0;i<8;i++){int nx=x+dx[i];int ny=y+dy[i];if(nx>=1&&nx<=n&&ny>=1&&ny<=n){if(a[nx][ny]==a[x][y]&&!vis[nx][ny]){vis[nx][ny]=true;q.push({nx,ny});}if(a[nx][ny]<a[x][y]){is_v=false;}if(a[nx][ny]>a[x][y]){is_r=false;}				}}}if(is_r)cntr++;if(is_v)cntv++;
}int main(){cin>>n;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++){for(int j=1;j<=n;j++){if(!vis[i][j]){bfs(i,j);}}}cout<<cntr<<" "<<cntv<<endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/883386.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

寒假集训专题五:搜索

ESAY1:自然数的拆分 P2404 自然数的拆分问题 题目描述 任何一个大于 \(1\) 的自然数 \(n\),总可以拆分成若干个小于 \(n\) 的自然数之和。现在给你一个自然数 \(n\),要求你求出 \(n\) 的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,…

多模态 AI 怎么玩?这里有 18 个脑洞

在 RTE 开发者社区,我们会和大家一起探索全球最前沿的 Real-Time AI 技术,和最有想法的新兴场景。Google 近期举办了一场名为「MultiModal Hackathon」的限时编程活动,聚焦于 多模态与 Gemini 2.0 的最新能力。活动汇聚了 200 多位开发者,共同探索多模态 AI、实时 AI、生成…

Svelte 最新中文文档翻译(7)—— snippet 与 @render

前言 Svelte,一个非常“有趣”、用起来“很爽”的前端框架。从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1:Svelte 以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非常适合构…

基环树 DP:学习笔记

总述 定义 基环树,是一个 \(N\) 个点和 \(N\) 条边的连通图,特征是图中有且仅有一个环。特别的,如果不连通且每个连通块的点数和边数都相等,那么这就是一个基环树森林。 基环树 DP,顾名思义,就是在一个基环树上 DP,或是 DP 的结构类似基环树。相对于正常的树型 DP,一般…

数字孪生如何让GIS场景视效瞬间高大上?带你了解鲸孪生中的GIS系统

GIS与数字孪生的结合非常紧密,而山海鲸可视化作为一个数字孪生平台,也将GIS系统整合在了鲸孪生功能之中。 GIS中包含了大量的数据,例如遥感数据、地形数据、倾斜摄影数据等,能够为数字孪生系统提供非常好的补充。同时,传统的GIS系统整体视觉效果相对较差,与其他模型和数据…

2 分支 多个思路

利用分支,你就可以在同一个代码基础上同时处理多个完全没有关联、相互独立的工作。考虑以下场景。 假设你正在改一个 Bug-A,此时已经产生了大量的代码修改,并且离修复完成还有很长一段时间(起码得明天)。此时,有一个着急但简单的 Bug-B 需要你立即完成,并在一个小时内同…

记录一种DAG计数方法与一个配套技巧

记录一种DAG计数方法与一个配套技巧 定义 \(f_S\) 表示集合 \(S\) 中的点构成的合法 DAG 子图的方案数。假设找到 DAG 中一个入度为 \(0\) 的节点 \(x\),那么很明显 \(f_S=\sum_{x}f_{S\setminus \{x\}}\),这明显要算重因为 \(S\setminus \{x\}\) 中也有入度为 \(0\) 的点。 …

野鸡题手写题解整合

浴谷正在蒸蒸日上,专栏区怕是马上要倒闭了。 CF2026F 题 题。题外话:这场有点水平,E 题让我重拾了最大权闭合子图的记忆。 首先考虑没有这个可持久化(只有 \(2,3,4\) 操作)怎么做。\(0/1\) 背包问题,动态维护当前的 dp 数组 \(f_i\) 表示总体积 \(\sum p\) 不超过 \(i\) …

鸿蒙开发:了解@Builder装饰器

@Builder装饰是鸿蒙UI开发中,非常重要的一个装饰器,在实际的开发中,合理且正确的使用,能够让我们的代码更加的简洁前言本文代码案例基于Api13,温馨提示:内容相对来说比较简单,如果您已掌握,略过即可。如果说一个页面中组件有很多,我们都统一写到build函数中,显而易见…

P1020 [NOIP 1999 提高组] 导弹拦截(dilworth)

这道题真的做的我鬼火冒,尤其是这个第二问要用到dilworth但是我看讲解完全不知道他们在讲什么,我看了好久才理解,一个数组至少可以由几个不增子序列覆盖就等于严格单调递增的最长子序列的长度,如果是至少可以由几个严格递减子序列覆盖就等于最长单调不减子序列的长度,然后…

Linux系统介绍

1. Linux介绍 Linux和windows一样也是一个操作系统,但是与windows不同的是,Linux是一套开放源码的代码程序、并且可以自由传播的类unix操作系统软件。 Linux系统主要被应用于服务端、嵌入式开发和个人PC桌面3大领域,一般的WEB项目都是部署在Linux操作系统上。 Linux是一个基…