这题一开始直接用暴力的DFS来做,果然到25的规模就挂了.
vector<bool> visited(50, false);
vector<vector<int> > vec_row(50);
vector<vector<int> > vec_col(50); bool findPath(vector<int> &x, vector<int> &y, int idx, int depth, int direction) {
if (depth == x.size()) return true;
visited[idx] = true;
if (direction == 0) {
int row = x[idx];
for (int i = 0; i < vec_row[row].size(); i++) {
if (!visited[vec_row[row][i]]) {
if (findPath(x, y, vec_row[row][i], depth+1, 1))
return true;
}
}
} else {
int col = y[idx];
for (int i = 0; i < vec_col[col].size(); i++) {
if (!visited[vec_col[col][i]]) {
if (findPath(x, y, vec_col[col][i], depth+1, 0))
return true;
}
}
} visited[idx] = false;
return false;
} //如果存在满足条件的遍历,返回true,否则返回false
bool existPath(vector<int> &x, vector<int> &y) {
int k = x.size();
if (k == 0) return true;
for (int i = 0; i < k; i++) {
vec_row[x[i]].push_back(i);
vec_col[y[i]].push_back(i);
}
for (int i = 0; i < k; i++) {
if (findPath(x, y, i, 1, 0) ||
findPath(x, y, i, 1, 1)) {
return true;
}
}
return false;
}
正确的做法是转化成欧拉回路:http://www.itint5.com/discuss/22/%E7%9B%B4%E8%A7%92%E8%B7%AF%E7%BA%BF%E9%81%8D%E5%8E%86%E6%A3%8B%E7%9B%98
这题可以直接转换为欧拉回路(路径)问题,这样,如果有解的时候要输出遍历路径的时候,也比较好办了。
具体的转换方式为:n,m的棋盘,建一个包含n+m个顶点的图G(为了方便说明,类似二分图将其分为两列,左边n个顶点,右边m个顶点,分别代表n行和n列)。对于目标格子(i,j),左边第i个顶点和右边第j个顶点连一条边。最后的问题其实就是问转换之后的图G是否存在欧拉欧拉回路或者欧拉路径。
证明:相邻两步为直角,其实就是从某一行变到某一列。访问图G中的一条边,意味着访问棋盘中的一个目标点。由于图G中的边只连接左边的点(代表某一行)和右边的点(代表某一列),因此访问一条边就意味着从某一行变到了某一列,也就是转直角了。
所以问题变为能否从一点出发访问G中的所有边有且仅有一次。这个就是欧拉回路问题了。
所以欧拉路径是:1.连通;2.奇点为2,为0时是欧拉回路。
这里的连通我用并查集来做。注意写并查集的merge时,要先找到根,再merge。
vector<int> djset; int find(int i) {
int x = i;
while (djset[x] != x) {
x = djset[x];
}
djset[i] = x;
return x;
} void merge(int i, int j) {
djset[find(i)] = djset[find(j)];
} //如果存在满足条件的遍历,返回true,否则返回false
bool existPath(vector<int> &x, vector<int> &y) {
vector<int> axis(100, 0);
// 计算奇点数目
for (int i = 0; i < x.size(); i++) {
axis[x[i]] = !axis[x[i]]; // 奇偶变换
}
for (int i = 0; i < y.size(); i++) {
axis[y[i]+50] = !axis[y[i]+50];
}
int count = 0;
for (int i = 0; i < axis.size(); i++) {
if (axis[i]) count++;
}
if (count != 0 && count != 2) return false; djset.resize(x.size());
for (int i = 0; i < djset.size(); i++) {
djset[i] = i;
} // 判断连通性
for (int i = 0; i < x.size(); i++) {
for (int j = i+1; j < x.size(); j++) {
if (x[i] == x[j]) {
merge(i, j);
}
}
}
for (int i = 0; i < y.size(); i++) {
for (int j = i+1; j < y.size(); j++) {
if (y[i] == y[j]) {
merge(i, j);
}
}
} for (int i = 0; i < x.size(); i++) {
if (find(i) != find(0)) {
return false;
}
}
return true;
}
[itint5]直角路线遍历棋盘的更多相关文章
-
POJ_2488——骑士遍历棋盘,字典序走法
Description Background The knight is getting bored of seeing the same black and white squares again ...
-
visual_c++外挂教程(详细)
课程分四个大章节 初级篇,中级篇,进阶篇,高级篇 初级篇内容:编写一个完整的,简单的外挂 C++的数据类型:Byte,Word,DWORD,int,float API函数的调mouse_event,G ...
-
NOI 题库 8465
8465 马走日 描述 马在中国象棋以日字形规则移动. 请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点. ...
-
chineseChess
最近学习了chineseChess的Qt实现,把一些东西总结一下: 实现功能: 1.人人对战 2.人机对战 3.网络版 一.基础性工作:(人人对战) 1.棋盘和棋子的绘制(QPinter,drawLi ...
-
noi 8465 马走日
8465:马走日 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 1024kB 描述 马在中国象棋以日字形规则移动. 请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y ...
-
poj 3279 Fliptile
题意:一个n * m的棋盘,0或1,每次改变一个格子时同时改变上下左右的格子,问用最少次数将棋盘全变成0的策略. 题解:用二进制压缩第一行更改的状态,之后遍历棋盘,如果当前格子为1则改变下方的格子,记 ...
-
听说alphago又要挑战sc2了?——我眼中的人工智能
乱谈: 之前alphago进行的围棋比赛相当火爆. 一时间我的朋友圈都爆了,因为同学以及相关专业的同学都在发这个,毕竟逼格一下就起来了,我也大肆转发.各种角度,不同层次的不同深度的文章也都扫了几眼. ...
-
web版扫雷小游戏(二)
接上篇~~第一次写这种技术博客,发现把自己做的东西介绍出来还是一件脑力活,不是那么轻松啊,好吧,想到哪写到哪,流水记录之,待完成之后再根据大家的意见进行修改吧. 游戏实现 根据对扫雷游戏的体验和分析, ...
-
疯狂Java讲义 第一章控制台五子棋(代码分析)
package com.test; public class Chessboard { //定义二维数组作为棋盘 private String[][] board; //定义棋盘大小 public s ...
随机推荐
-
iOS摇一摇手机,播放微信摇一摇音效
实现微信摇一摇播放音效,代码如下:- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{ if (motio ...
-
EF 更新条目时出错。有关详细信息,请参见内部异常。
现象:使用EF新增记录时,一直报上述异常,网上说是值为空.主键外键未设等原因导致,但是改正这些情况下问题依然 解决过程:异常中有一句(请参见内部异常),一直都没有当回事,后来实在没办法就静下心来看了看 ...
- (转载)小课堂UI-有关配色的一个小技巧
-
Ubuntu 12.04开启3D桌面特效
1.设定软件源,更新软件 点击左边栏Dash主页(Ubuntu图标),输入更新管理器,会出现更新管理器,打开后点设置,弹出软件源对话框,为确保能够正常更新,选主服务器 点击检查,更新完后,点重启 2. ...
-
详解Centos默认磁盘分区
对于有经验的Linux系统管理员,在安装系统之前都会对系统的分区进行规划:针对这一需求,下面就通过默认的Centos分区与大家分享一些关于Linux系统的知识.Linux系统的磁盘命名规范:硬盘类型标 ...
-
yii批量插入的方法
public function insertSeveral($table, $array_columns) { $sql = ''; $params = array(); $i = 0; foreac ...
-
【easy】530. Minimum Absolute Difference in BST
找BST树中节点之间的最小差值. /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode ...
-
Eclipse无法正常启动,弹出对话框内容为 A Java Runtime...
1.Eclipse无法正常启动,弹出对话框内容为 A Java Runtime...如下图: 原因分析:由于软件版本的更新或者安装其他开发软件无意之间修改了配置文件中的路径,众所周知,Java虚拟机( ...
-
SQL Server 函数之日期格式化函数
SQL Server 函数之日期格式化函数 高文龙关注0人评论612人阅读2017-09-23 13:47:07 SQL Server 函数之日期格式化函数 对于一些经常写SQL Server执行语句 ...
-
java JDBC (六) org.apache.commons.dbutils 增删改
dbutils是apache封装了JDBC的工具类,比mysql-connector更方便些 下载地址:http://commons.apache.org/proper/commons-dbutils ...