F - 环
#include <iostream>
#include <vector>
using namespace std;
const int N = 2e5;
int nxt[N], vis[N];
int start = -1;
void dfs(int u)
{
vis[u]++;
if (vis[u] == 2) {
start = u;
return;
}
dfs(nxt[u]);
}
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> nxt[i];
}
for (int i = 1; i <= n; i++) {
if (vis[i] == 0) {
dfs(i);
if (start != -1) {
break;
}
}
}
int u = start;
vector<int>ans = { start };
while (start != nxt[u]) {
u = nxt[u];
ans.push_back(u);
}
cout << ans.size() << endl;
for (int x : ans) {
cout << x << " ";
}
cout << endl;
return 0;
}
解题流程:
1,先做,后做:
第一步,定义全部变量
(1)N题目规定的最大值
(2)nxt数组:存输入的顶点顺序,vis数组是用来在DFS中判断是否出现了环
(3)start:用来存环第一个顶点,初始值设为-1,后续方便用start是否==-1来判断是否出现环
第二步,定义DFS函数
(1)vis[x]++,表示x的遍历次数
(2)如果vis[x]==2,说明出现了环,start=x,直接返回
(3)否则,就调用递归函数dfs(nxt[x]),nxt[x]才是x指向的顶点
第三步,main函数
(1)输入nxt数组的元素,从1开始
(2)循环遍历,如果vis[i]==0,那就递归调用dfs(i),当start!=-1时就是找到了一个环,这时就break循环
(3)用u存储start的值,设置ans数组,用来存环的每一个顶点,第一个元素设为start
(4)while(start!=nex[u])就更新u的值为nxt[u],并把u更新后的值push_back进ans数组
(5)最后按照题目要求输出ans元素个数和每个元素
2,知识点套路:
(1)深度优先搜索
(2)环
3,前提条件:
环
4,注意事项:
(1)start最好设置一个初始值
(2)不要搞混x和nxt[x]的含义
G - 滑冰
#include <iostream>
#include <string>
using namespace std;
string s[201];
int n, m;
int vis[201][201];
bool ok[201][201];
int dx[] = { 0,0,-1,1 };
int dy[] = { 1,-1,0,0 };
void dfs(int x, int y, int d)
{
ok[x][y] = true;
while (s[x + dx[d]][y + dy[d] ]!= '#') {
x += dx[d];
y += dy[d];
ok[x][y] = true;
}
if (vis[x][y])return;
else {
vis[x][y] = 1;
for (int i = 0; i < 4; i++) {
dfs(x, y, i);
}
}
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> s[i];
s[i] = '#' + s[i];
}
dfs(2, 2, 0);
dfs(2, 2, 2);
int ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
ans += ok[i][j];
}
}
cout << ans << endl;
return 0;
}
解题流程:
1,先做,后做:
第一步,初始化相关的变量:
(1)201是题目限制的N,M的最大值+1,
(2)n,m为图的行列,
(3)vis二维数组是标记已经走过的点,
(4)OK数组是标记的可达路径,一开始就在DFS中把ok[x][y]=true,是因为main里面调用第一遍函数的时候,传入的是(2,2),这个点一定是冰,而后面调用之前,都会判断过不是‘#’之后才标记为true
(5)设置方向向量dx和dy,分别是上下左右变化时x,y的变化量
第二步,写DFS函数
(1)标记ok[x][y]为true,可达路径
(2)循环遍历(深度优先搜索)一个方向,不是障碍物,就一直遍历,直到遇见障碍物,同时更新x,y的值
(3)如果,此时vis[x][y]==1,那么说明这个点已经遍历过了,return
(4)否则,就把这个点标记为已经遍历,即,vis[x][y]=1;在循环四次(四个方向)去调用DFS函数递归
第三步,main函数:
(1)传入n,m;并在循环输入s[i]后,加上一句,s[i]='#'+s[i],顺序不能调换,因为题目说了,周围边界都是障碍物,这里就是把每行的最左边都设置为障碍物,防止数组的越界行为
(2)dfs(2,2,0),dfs(2,2,2),分别向是向上和向左搜索,只需要两个方向的就可以了(上+右、上+左、下+左、下+右)
2,知识点套路:
(1)DFS深度优先搜素
(2)用方向向量
3,前提条件:
图
4,注意事项:
(1)一定要在s数组的左边边界设置多一个#
(2)
E - 串反转
#include <iostream>
#include <string>
#include <set>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
set<string>unique_sticks;
for (int i = 0; i < n; i++) {
string s;
cin >> s;
string r_s = s;
reverse(r_s.begin(), r_s.end());
if (r_s < s) {
unique_sticks.insert(r_s);
}
else {
unique_sticks.insert(s);
}
}
cout << unique_sticks.size() << endl;
return 0;
}
解题流程:
1,先做,后做:
(1)首先明白,题目的要求是要求不相同的三根根子,这时候应该要想到set,set可以自动去重
(2)每输入一个String之后,我们都直接判断它和它的reverse哪个字典序小,我们把字典序小的Insert到set里面,set可以自动去重,最后set的元素数量就是我们要的
2,知识点套路:
(1)set可以自动去重
(2)reverse函数的调用
(3)字典序
3,前提条件:
4,注意事项:
(1)其实insert字典序大的也可以,只要选一种就行了
D - 一起度假
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
int n, d;
cin >> n >> d;
vector<string>vec(n+1);
vector<bool>space(d + 1, true);
for (int i = 1; i <= n; i++) {
cin >> vec[i];
string s = vec[i];
for (int j = 0; j < s.length(); j++) {
if (space[j + 1] == true && s[j] == 'o')space[j + 1] = true;
else space[j + 1] = false;
}
}
int count = 0;
vector<int>ret;
for (int i = 1; i <= d; i++) {
if (space[i] == true) {
count++;
}
else {
ret.push_back(count);
count = 0;
}
}
ret.push_back(count);
int m = 0;
for (int i = 0; i < ret.size(); i++) {
m = max(m, ret[i]);
}
cout << m << endl;
return 0;
}
解题流程:
1,先做,后做:
(1)先把Space初始设为true,只有Space[j+1]==true且s[j]=='o'的时候才能把这个位置的Space设置为true,因为要所有人都有空才能使公共的空余空间
(2)连续的空闲天数可能有多个,要比较出最大的才输出
2,知识点套路:
3,前提条件:
4注意事项:
(1)一定要分请各个变量名字,不要搞混——解决:自己定义变量名的时候要注意取一个自己不容易混的名字
(2)要连续的天数,中最大的连续天数
(3)在定义m之前要把此时的count push进ret中,因为最后一个count没来得及push进去
C - 最小字典序
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string s;
cin >> s;
sort(s.begin(), s.end());
cout << s << endl;
return 0;
}
解题流程:
1,先做,后做:
2,知识点套路:字典序是什么,怎么比较大小的
3,前提条件:
4,注意事项: