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笔画成;

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

哈密顿图:遍历所有顶点

欧拉:遍历所有边

相关推荐
破-风2 小时前
leetcode-------mysql
算法·leetcode·职场和发展
自不量力的A同学6 小时前
如何利用人工智能算法优化知识分类和标签?
人工智能·算法·分类
CodeJourney.6 小时前
PyTorch不同优化器比较
人工智能·pytorch·算法·能源
winner88816 小时前
对比学习损失函数 - InfoNCE
学习·算法·对比学习·infonce
南宫生7 小时前
力扣-数据结构-12【算法学习day.83】
java·数据结构·学习·算法·leetcode
KeyPan7 小时前
【数据结构与算法:五、树和二叉树】
java·开发语言·数据结构·人工智能·算法·机器学习·计算机视觉
WBingJ7 小时前
机器学习基础-贝叶斯分类器
人工智能·算法·机器学习
Lenyiin8 小时前
第431场周赛:最长乘积等价子数组、计算字符串的镜像分数、收集连续 K 个袋子可以获得的最多硬币数量、不重叠区间的最大得分
c++·算法·leetcode·周赛·lenyiin
行知SLAM8 小时前
第0章 机器人及自动驾驶SLAM定位方法全解析及入门进阶学习建议
人工智能·算法·机器人·自动驾驶
起名方面没有灵感10 小时前
力扣23.合并K个升序链表
java·算法