19712 数字接龙

cpp 复制代码
/*
 我觉得重要的理解点:
  1.四维数组白表示一个点从另一个点沿对角线的方式进行移动,如果这个元素的值为真则表示这样的移动存在。 
  2.按照0->k-1的顺序移动。这个要求的实现方法也值得学习 
  3.count和index的含义: index表示索引,表示第index步。
  		当index=0表示在起点,ndex=1表示从原点出发走了一步。
		count表示走过的格子数。count=n*n表示所有的格子都已经走过。
*/ 
  
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n, k, fx[8][2] = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}}; // 2列8行的数组,按照行初始化
//从向左移动开始。顺时针的移动顺序
//即正左,左上,正上,右上,正右,右下,正下,左下
int maps[11][11]; // 存储地图信息的二维数组
bool vis[11][11], b = false, check[11][11][11][11]; // 访问标记,结束标记,交叉检查
vector<int> v; // 存储路径
//四维数组check[a][b][c][d]表示从(a,b)->(c,d)其中此两点为对角线关系,
//即check[a][b][c][d]表示(a,b)通过斜线访问到(c,d);
//同样的check[c][d][a][b]表示从(c,d)->(a,b)

// 深度优先搜索函数
void dfs(int x, int y, int index, int count) {
    if (b) return; // 剪枝,如果已经找到答案则不再继续搜索
    if (x == n && y == n && count == n * n) { // 判断是否到达终点
        //count表示走过的格子总数
        b = true;
        for (int i = 0; i < v.size(); i++) cout << v[i]; // 输出路径
        return;
    
    for (int i = 0; i < 8; i++) { // 遍历所有可能的移动方向
        int xx = x + fx[i][0], yy = y + fx[i][1]; // 新坐标
        if (xx < 1 || yy < 1 || xx > n || yy > n || vis[xx][yy]) continue; // 判断移动是否合法
        
        if (maps[xx][yy] != (index + 1) % k) continue; 
        //index"索引". index=0表示在当前位置
        //index+1 表示下一个步骤的位置
        //maps[x][y]+1=maps[xx][yy]
        //[x][y]时index=index;
        //[xx][yy]index=index+1;
        //%k使得能够循环判断。将值控制在0->k-1的范围之内。
        //判断是否按照0~k-1的顺序走.
        if (i % 2 && check[x + fx[i][0]][y][x][y + fx[i][1]] || check[x][y + fx[i][1]][x + fx[i][0]][y]) continue; // 交叉检查
        //if触发条件:对角线移动且存在交叉
        //示意图:  a b
        //         c d
        //判断交叉的原理:假设从c(x,y)点出发,当i=3时表示向右上移动到b;
        //此时check[x + fx[i][0]][y][x][y + fx[i][1]]为check[x+1][y][x][y+1]
        //即a->d是否为1
        //同时判断check[x + fx[i][0]][y][x][y + fx[i][1]] (check[x][y+1][x+1][y])
        //即d->a是否为1
        //有一个为1则为交叉
        vis[xx][yy] = true; // 标记为已访问
        if (i % 2) {check[x][y][xx][yy] = true; check[xx][yy][x][y] = true;} // 标记交叉点
        v.push_back(i); // 答案的写入
        dfs(xx, yy, (index + 1) % k, count + 1); // 递归
        vis[xx][yy] = false; // 回溯
        //回溯的原因
        //1.没有按照规定的顺序走 0->k-1
        //2.存在交叉
        //3.越界或者到终点

        //回溯之后说明这个点非法,则将标记清除,不影响其他路径规划。
        if (i % 2) {check[x][y][xx][yy] = false; check[xx][yy][x][y] = false;} // 回溯交叉点
        v.pop_back(); 
    }
}


int main() {
    cin >> n >> k; // 输入网格大小和要求
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> maps[i][j]; // 输入网格信息
        }
    }
    vis[1][1] = true; // 从(1,1)开始
    dfs(1, 1, 0, 1); // 深度优先搜索
   if (!b) cout << -1; // 如果没有找到答案,输出-1
    return 0;
}

无向图存在欧拉回路(回到原点)的充要条件:每个点的度数为偶数

度数:连接一个点的条数。 为奇数的点为奇点,偶数为偶点。

不闭合的欧拉路径存在的充要条件:奇顶点的个数等于0或2;

定理2:一个无向图有2n个奇顶点,最少需要n笔画成;

一个图是否能够不重复的遍历所有顶点:能则为哈密顿图

哈密顿图:遍历所有顶点

欧拉:遍历所有边

相关推荐
mit6.82427 分钟前
[Sum] C++STL oj常用API
c++·算法·leetcode
槐月初叁33 分钟前
C++洛谷基础练习题及解答
开发语言·c++·算法
Archer1941 小时前
C++基础——从C语言快速入门
数据结构·c++·算法
好易学数据结构1 小时前
可视化图解算法:链表中环的入口节点(环形链表 II)
数据结构·算法
啥都鼓捣的小yao1 小时前
Python手写机器学习的“线性回归”算法
python·算法·机器学习
一只_程序媛1 小时前
【leetcode hot 100 114】二叉树展开为链表
算法·leetcode·链表
萧瑟其中~2 小时前
前缀和算法第一弹(一维前缀和和二维前缀和)
算法
_星辰大海乀2 小时前
刷题练习笔记
java·数据结构·笔记·算法·链表·list·idea
苏言の狗2 小时前
二进制矩阵全零转换问题 | DFS
算法·深度优先
夜猫程序猿2 小时前
算法题刷题方法记录(蓝桥杯、Leetcode)
算法·leetcode·蓝桥杯