机缘
提示:可以和大家分享最初成为创作者的初心
机缘
我最初成为创作者的初心来源于对编程的热爱和分享的渴望。作为一名计算机专业的学生,我参与过一些实际项目和竞赛,积累了不少经验,而每一次完成一个项目、解决一个难题时的成就感也促使我希望把这些经验分享出来。通过创作,我不仅能够记录日常学习和实战项目中的思考过程,还可以通过文章交流技术,帮助其他在编程道路上遇到类似问题的人。比如,在编写前端开发技巧、数据结构优化或者算法实现的文章时,我都会格外投入,因为这些不仅能提升自己的表达能力,也有助于加深对知识的理解。
收获
在创作的过程中,我收获了许多温暖的关注。比如,目前大约有240位粉丝在关注我的更新,每当看到他们的赞和评论,我都非常高兴。有一次,一篇介绍双向广度优先搜索的文章获得了309次点赞、7次评论和24407次阅读量。这些积极的反馈和互动让我更有动力去分享自己的学习心得,也让我认识到很多志同道合的编程爱好者。通过交流,我结识了不少在算法、数据分析和前端开发等领域的优秀同行,我们彼此学习,共同成长。
日常
如今,创作已经成了我生活的一部分。我发现,每当学习或完成新的编程任务时,都会产生一种强烈的想法,把这些过程和方法分享给更多人。在有限的时间和精力下,我会在每晚编程后,将其中的亮点和技巧记录下来,稍作整理后发布成文章。这样不仅提升了自己的表达和总结能力,还能时常回顾这些点滴,找到进步的方向。
成就
提示:你过去写得最好的一段代码是什么? 请用代码块贴出来
例如:
- 某个解题代码
#include <string> #include <iostream> #include <cstdio> #include <queue> #include <vector> #include <cstring> // 包含 C 风格字符串处理 #include <algorithm> // 包含常用算法 using namespace std; // 使用标准命名空间 const int maxn = 5e5 + 10; // 定义最大状态数量 int vis[maxn]; // 定义正向搜索访问标记数组 int vis2[maxn]; // 定义反向搜索访问标记数组 char d[10] = { "udlr" }, d2[10] = { "durl" }; // 定义移动方向字符数组 int dir[4] = { -3, 3, -1, 1 }; // 定义方向对应的索引变化量 int ha[9] = { 40320, 5040, 720, 120, 24, 6, 2, 1, 1 }; // 阶乘预处理数组,用于计算哈希值 string a, b = "123456780"; // 定义初始状态和目标状态字符串 // 记录节点信息的结构体 struct node { int num; // 当前节点编号 char ch; // 从父节点到当前节点的移动方向 } pre[maxn]; // 定义节点信息数组 // 用于存储状态及其编号的结构体 struct node2 { int num; // '0'所在的位置 string s; // 状态字符串 } e; // 定义初始状态结构体 // 递归输出解法路径 void show(int x) { if (pre[x].num == -1) // 如果是初始节点,返回 return; show(pre[x].num); // 递归输出前一个节点 printf("%c", pre[x].ch); // 输出当前节点的移动方向 } // 计算状态的哈希值 int getha(string s) { int sum = 0; // 初始化哈希值 for (int i = 0; i < 9; i++) { // 遍历字符串 int k = 0; // 逆序数计数 for (int j = i + 1; j < 9; j++) { // 计算逆序数 if (s[j] < s[i]) k++; } sum += k * ha[i]; // 计算哈希值 } return sum; // 返回哈希值 } // 广度优先搜索,包含双向搜索 void bfs() { int q = getha(e.s); // 计算初始状态的哈希值 queue<node2> q1; // 定义正向搜索队列 queue<node2> q2; // 定义反向搜索队列 vis[q] = 1; // 标记初始状态已访问 node2 f, g; // 定义状态结构体 f.s = b; // 设置目标状态 f.num = 8; // 设置'0'的位置 int p = getha(f.s); // 计算目标状态的哈希值 int x, k; // 定义临时变量 vis2[p] = 2; // 标记目标状态已访问 pre[1].num = -1; // 初始化路径记录 pre[2].num = -1; // 初始化路径记录 int num = 2; // 设置状态编号初始值 q1.push(e); // 初始状态入队 q2.push(f); // 目标状态入队 while (!q1.empty() && !q2.empty()) { // 如果两个队列都不为空 f = q1.front(); // 取出正向搜索队列的队首元素 q1.pop(); // 弹出队首元素 p = getha(f.s); // 计算当前状态的哈希值 if (vis2[p]) { // 如果反向搜索已访问 show(vis[p]); // 输出正向路径 k = vis2[p]; // 取出反向路径起点 while (pre[k].num != -1) { // 输出反向路径 printf("%c", pre[k].ch); // 输出方向字符 k = pre[k].num; // 取下一个节点 } printf("\n"); // 输出换行 return; // 结束搜索 } for (int i = 0; i < 4; i++) { // 遍历四个方向 if (i == 0 && f.num < 3) continue; // 如果不能向上移动,跳过 if (i == 1 && f.num > 5) continue; // 如果不能向下移动,跳过 if (i == 2 && f.num % 3 == 0) continue; // 如果不能向左移动,跳过 if (i == 3 && f.num % 3 == 2) continue; // 如果不能向右移动,跳过 x = f.num + dir[i]; // 计算移动后的'0'位置 g = f; // 复制当前状态 swap(g.s[f.num], g.s[x]); // 交换'0'与目标位置 q = getha(g.s); // 计算新状态的哈希值 if (vis[q]) continue; // 如果新状态已访问,跳过 vis[q] = ++num; // 标记新状态已访问,并记录编号 g.num = x; // 更新'0'的位置 pre[num].num = vis[p]; // 记录路径信息 pre[num].ch = d[i]; // 记录移动方向 q1.push(g); // 新状态入队 } f = q2.front(); // 取出反向搜索队列的队首元素 q2.pop(); // 弹出队首元素 p = getha(f.s); // 计算当前状态的哈希值 if (vis[p]) { // 如果正向搜索已访问 show(vis[p]); // 输出正向路径 k = vis2[p]; // 取出反向路径起点 while (pre[k].num != -1) { // 输出反向路径 printf("%c", pre[k].ch); // 输出方向字符 k = pre[k].num; // 取下一个节点 } printf("\n"); // 输出换行 return; // 结束搜索 } for (int i = 0; i < 4; i++) { // 遍历四个方向 if (i == 0 && f.num < 3) continue; // 如果不能向上移动,跳过 if (i == 1 && f.num > 5) continue; // 如果不能向下移动,跳过 if (i == 2 && f.num % 3 == 0) continue; // 如果不能向左移动,跳过 if (i == 3 && f.num % 3 == 2) continue; // 如果不能向右移动,跳过 x = f.num + dir[i]; // 计算移动后的'0'位置 g = f; // 复制当前状态 swap(g.s[f.num], g.s[x]); // 交换'0'与目标位置 q = getha(g.s); // 计算新状态的哈希值 if (vis2[q]) continue; // 如果新状态已访问,跳过 vis2[q] = ++num; // 标记新状态已访问,并记录编号 g.num = x; // 更新'0'的位置 pre[num].num = vis2[p]; // 记录路径信息 pre[num].ch = d2[i]; // 记录移动方向 q2.push(g); // 新状态入队 } } printf("unsolvable\n"); // 如果队列为空,输出 unsolvable } int main() { while (getline(cin, a)) { // 读取输入行 int n, k = 0; // 定义字符串长度和逆序数计数器 n = a.size(); // 获取输入字符串长度 e.s = ""; // 初始化状态字符串 for (int i = 0, j = 0; i < n; i++) { // 遍历输入字符串 if (a[i] != ' ') { // 如果不是空格 if (a[i] == 'x') { // 如果是'x' e.num = j; // 记录'0'的位置 e.s += '0'; // 将'x'转换为'0' } else { e.s += a[i]; // 添加字符到状态字符串 } j++; // 字符计数器加1 } } for (int i = 0; i < 9; i++) { // 遍历状态字符串 if (e.s[i] == '0') continue; // 如果是'0'跳过 for (int j = 0; j < i; j++) { // 计算逆序数 if (e.s[j] == '0') continue; // 如果是'0'跳过 if (e.s[j] > e.s[i]) k++; // 如果前面的数比当前数大,逆序数加1 } } memset(vis2, 0, sizeof(vis2)); // 重置反向访问标记数组 memset(vis, 0, sizeof(vis)); // 重置正向访问标记数组 if (k & 1) { // 如果逆序数为奇数 printf("unsolvable\n"); // 输出 unsolvable } else { bfs(); // 否则进行广度优先搜索 } } return 0; // 程序结束 }
憧憬
在未来的职业规划中,我希望能进一步拓展在算法与数据结构方面的专业知识,并在某天成为技术社区中的一名受欢迎的创作者。