http://www.itint5.com/oj/#22

这题一开始直接用暴力的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]直角路线遍历棋盘的更多相关文章

  1. POJ_2488——骑士遍历棋盘,字典序走法

    Description Background The knight is getting bored of seeing the same black and white squares again ...

  2. day53-马踏棋盘

    马踏棋盘 1.算法优化的意义 算法是程序的灵魂,为什么有些程序可以在海量数据计算时,依旧保持高速计算? 编程中算法很多,比如八大排序算法(冒泡.选择.插入.快排.归并.希尔.基数.堆排序).查找算法. ...

  3. visual_c++外挂教程(详细)

    课程分四个大章节 初级篇,中级篇,进阶篇,高级篇 初级篇内容:编写一个完整的,简单的外挂 C++的数据类型:Byte,Word,DWORD,int,float API函数的调mouse_event,G ...

  4. NOI 题库 8465

    8465  马走日 描述 马在中国象棋以日字形规则移动. 请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点. ...

  5. chineseChess

    最近学习了chineseChess的Qt实现,把一些东西总结一下: 实现功能: 1.人人对战 2.人机对战 3.网络版 一.基础性工作:(人人对战) 1.棋盘和棋子的绘制(QPinter,drawLi ...

  6. noi 8465 马走日

    8465:马走日 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  1024kB 描述 马在中国象棋以日字形规则移动. 请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y ...

  7. poj 3279 Fliptile

    题意:一个n * m的棋盘,0或1,每次改变一个格子时同时改变上下左右的格子,问用最少次数将棋盘全变成0的策略. 题解:用二进制压缩第一行更改的状态,之后遍历棋盘,如果当前格子为1则改变下方的格子,记 ...

  8. 听说alphago又要挑战sc2了?——我眼中的人工智能

    乱谈: 之前alphago进行的围棋比赛相当火爆. 一时间我的朋友圈都爆了,因为同学以及相关专业的同学都在发这个,毕竟逼格一下就起来了,我也大肆转发.各种角度,不同层次的不同深度的文章也都扫了几眼. ...

  9. web版扫雷小游戏(二)

    接上篇~~第一次写这种技术博客,发现把自己做的东西介绍出来还是一件脑力活,不是那么轻松啊,好吧,想到哪写到哪,流水记录之,待完成之后再根据大家的意见进行修改吧. 游戏实现 根据对扫雷游戏的体验和分析, ...

随机推荐

  1. (转)卸载和安装LINUX上的JDK

    卸载默认的: 用root用户登陆到系统,打开一个终端输入 # rpm -qa|grep gcj 显示内容其中包含下面两行信息 # java-1.4.2-gcj-compat-1.4.2.0-27jpp ...

  2. javascript笔记——jqGrid再次封装

    xingrunzhao js插件再次封装 demo 'use strict'; /** * commerce grid框架 * 依赖jqgrid */ (function ($_self, jQuer ...

  3. Js中的运算符

    运算符 运算符:就是可以运算的符号 比如 + .-.*./ 运算符包括: 算术运算符 比较运算符 逻辑运算符 赋值运算符 字符串运算符 1.算术运算符 +.-.*./.%(求余数).++.-- ++: ...

  4. 定制的Server-Sent Events 聊天服务器

    //匿名聊天服务器 //将新的消息POST到/chat地址,或者以GET形式从通一个URL获取文本或事件流 //创建一个GET请求到"/"来返回一个简单的HTML文件,这个文件包括 ...

  5. Spring Mvc模式下Jquery Ajax 与后台交互操作

    1.基本代码 1)后台控制器基本代码 @Controller @RequestMapping("/user") public class UserController { @Aut ...

  6. [转]mysql-5.6.17-win32免安装版配置

    1. 下载mysql-5.6.17-win32:官网下载地址百度 2. 解压到自定义目录,我这里演示的是D:\wamp\mysql\ 3. 复制根目录下的my-default.ini,改名为my.in ...

  7. 多种的android进度条的特效源码

    多种的android进度条的特效源码,这个源码是在源码天堂那个网站上转载过来的,我已经修改一部分了,感觉很实用的,大家可以学习一下吧,我就不上传源码了,大家可以直接到那个网站上下载吧. 源码天堂下载地 ...

  8. asp.net 时间比较,常用于在某段时间进行操作

    DateTime.Compare(t1,t2)比较两个日期大小,排前面的小,排在后面的大,比如:2011-2-1就小于2012-3-2返回值小于零:  t1 小于 t2. 返回值等于零 : t1 等于 ...

  9. 一款js控制背景图片平铺

    背景图片的平铺方法有很多种,纯色背景,渐变背景,图片背景,今天讲的是移动端的图片背景~~~~ <style> html,body{;;} .body{background: url(ima ...

  10. Demo学习: ClientInfo

    ClientInfo 获取客户端环境参数,从0.9版本开始新增了TUniClientInfoRec对象,可以得到客户端的一些信息,之前为了获取浏览器版本号需要自己写函数,现在可以直接使用TUniCli ...