这道题如果直接用Dfs,运气好的话是可以直接过的。

  但如果要在Dfs的基础上加快速度,剪枝是必不可少的。

  我的剪枝策略:

    1.当前点(x,y)回到出发点至少需要 |x| +| y| 步,如果剩余的步数不足以达到当前所需的最小步数,则剪枝。比如在没有障碍的情况下,要求在4次行走时完成回路,如果第三次走到(2,4),那么计算得要回到出发点最少需要5步,但此时剩余4步,不可能走回出发点,因此可以剪枝。

    2.如果当前 x 或 y 的值,超过了所能走的步数的一半,则剪枝

    3.如果没有在最后一步就走到出发点,就剪枝。比如在没有障碍的情况下,要求在20次行走时完成回路,那么就很容易在第8次的时候就走回出发点(题目中的例子就是8次回到出发点),此时已经没有继续走第9次,因此可以剪枝。

  需要额外注意的一点是,此题中的x,y坐标是直角坐标系的坐标,而不是矩阵的坐标。

  

// #include <iostream>
// #include <cstring>
// #include <cstdio>
// #include <algorithm>
// #include <vector>
#include <bits/stdc++.h> using namespace std; struct Point{
int x, y;
Point(){}
Point(int a, int b){
x = a; y = b;
}
};
vector<Point> point;
int dirPath[30];
int dir[4][2] = {1, 0, 0, 1, 0, -1, -1, 0};
int revDir[4] = {3, 2, 1, 0};
char dirChar[10] = "ensw";
int N, K, C; void Read() {
scanf("%d%d", &N, &K);
point.clear();
int x, y;
for(int i=0; i<K; ++ i) {
scanf("%d%d", &x, &y);
point.push_back(Point(x, y));
}
} const int MAXN = 600;
const int OFFSET = 256;
bool vis[MAXN][MAXN];
bool IsVis(const Point &p) {
return vis[p.x+OFFSET][p.y+OFFSET];
} void SetVis(const Point &p, bool flag) {
vis[p.x+OFFSET][p.y+OFFSET] = flag;
} bool CanPut(const Point& p1, const Point& p2) {
if(p1.x == p2.x) {
for(size_t i = 0; i < point.size(); ++ i) {
if(point[i].x == p1.x && point[i].y >= p1.y && point[i].y <= p2.y) {
return false;
}else if(point[i].x == p1.x && point[i].y >= p2.y && point[i].y <= p1.y) {
return false;
}
}
} else if(p1.y == p2.y) {
for(size_t i = 0; i < point.size(); ++ i) {
if(point[i].y == p1.y && point[i].x >= p1.x && point[i].x <= p2.x) {
return false;
}else if(point[i].y == p1.y && point[i].x >= p2.x && point[i].x <= p1.x) {
return false;
}
}
}
return true;
} void Print() {
for(int i=1; i<N+1; i++) {
printf("%c", dirChar[dirPath[i]]);
}
printf("\n");
} void Dfs(Point p, int key) {
if(abs(p.x) + abs(p.y) > (key+N) * (N-key+1) >> 1) {
return ;
}
if(abs(p.x) > (1+N) * N >> 1 || abs(p.y) > (1+N) * N >> 1) {
return ;
}
if(key == N + 1) {
if(p.x == 0 && p.y == 0) {
++ C;
Print();
}
return ;
} else if(p.x == 0 && p.y == 0) {
return ;
}
for(int i=0; i<4; i++) {
if(dirPath[key - 1] != i && i != revDir[dirPath[key - 1]]) {
Point next( p.x + key * dir[i][0], p.y + key * dir[i][1] );
if(!IsVis(next) && CanPut(p, next)) {
dirPath[key] = i;
SetVis(next, true);
Dfs(next, key+1);
SetVis(next, false);
}
}
}
} int main() {
int T;
cin >> T;
while(T --) {
Read();
memset(vis, false, sizeof(vis));
Point start(0, 0);
C = 0;
for(int i=0; i<4; i++) {
Point next( start.x+dir[i][0], start.y+dir[i][1] );
if(CanPut(start, next)) {
dirPath[1] = i;
SetVis(next, true);
Dfs(next, 2);
SetVis(next, false);
}
}
printf("Found %d golygon(s).\n", C);
printf("\n");
}
return 0;
}

Uva 225 Golygons的更多相关文章

  1. UVA - 225 Golygons (黄金图形)(回溯)

    题意:平面有k个障碍点.从(0,0)出发,第一次走1个单位,……,第n次走n个单位,恰好回到(0,0),每次必须转弯90°,图形可以自交,但不能经过障碍点.按字典序输出所有移动序列,并输出序列总数. ...

  2. UVa 225 黄金图形(回溯+剪枝)

    https://vjudge.net/problem/UVA-225 题意:平面上有k个障碍点,从(0,0)出发,第一次走1个单位,第二次走2个单位,...第n次走n个单位,最后恰好回到(n,n).每 ...

  3. UVa 10012 - How Big Is It? 堆球问题 全排列+坐标模拟 数据

    题意:给出几个圆的半径,贴着底下排放在一个长方形里面,求出如何摆放能使长方形底下长度最短. 由于球的个数不会超过8, 所以用全排列一个一个计算底下的长度,然后记录最短就行了. 全排列用next_per ...

  4. Fast Matrix Operations(UVA)11992

    UVA 11992 - Fast Matrix Operations 给定一个r*c(r<=20,r*c<=1e6)的矩阵,其元素都是0,现在对其子矩阵进行操作. 1 x1 y1 x2 y ...

  5. Android Weekly Notes Issue #225

    Android Weekly Issue #225 October 2nd, 2016 Android Weekly Issue #225 本期内容包括: Android 7.0的Quick Sett ...

  6. uva 1354 Mobile Computing ——yhx

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABGcAAANuCAYAAAC7f2QuAAAgAElEQVR4nOy9XUhjWbo3vu72RRgkF5

  7. UVA 10564 Paths through the Hourglass[DP 打印]

    UVA - 10564 Paths through the Hourglass 题意: 要求从第一层走到最下面一层,只能往左下或右下走 问有多少条路径之和刚好等于S? 如果有的话,输出字典序最小的路径 ...

  8. UVA 11404 Palindromic Subsequence[DP LCS 打印]

    UVA - 11404 Palindromic Subsequence 题意:一个字符串,删去0个或多个字符,输出字典序最小且最长的回文字符串 不要求路径区间DP都可以做 然而要字典序最小 倒过来求L ...

  9. UVA&&POJ离散概率与数学期望入门练习[4]

    POJ3869 Headshot 题意:给出左轮手枪的子弹序列,打了一枪没子弹,要使下一枪也没子弹概率最大应该rotate还是shoot 条件概率,|00|/(|00|+|01|)和|0|/n谁大的问 ...

随机推荐

  1. Android项目开发五-《星星生活志》1.使用MediaRecorder录制音频

    Android设备实现录制音频的简单demo 转载请注明; http://blog.csdn.net/u013670933/article/details/26089487 代码例如以下: publi ...

  2. DIV+CSS解决IE6,IE7,IE8,FF兼容问题(转至http://www.douban.com/note/163291324/)

    2011-07-25 21:11:47     DIV+CSS解决IE6,IE7,IE8,FF兼容问题 1.IE8下兼容问题,这个最好处理,转化成IE7兼容就可以.在头部加如下一段代码,然后只要在IE ...

  3. (转)ios跳转到通用页面

    在代码中调用如下代码: [[UIApplicationsharedApplication] openURL:[NSURLURLWithString:@"prefs:root=LOCATION ...

  4. 跳出for循环

    如下面,有两个循环,break只能退出一个for循环,不能直接跳过第二个for循环 for (Type type : types) { for (Type t : types2) { if (some ...

  5. JavaSE_ 集合框架 总目录(15~18)

    JavaSE学习总结第15天_集合框架1 15.01 对象数组的概述和使用15.02 对象数组的内存图解15.03 集合的由来及与数组的区别15.04 集合的继承体系图解15.05 Collectio ...

  6. Java中Calender引用类型

    某些时候需要使用深拷贝: Calendar startTime = (Calendar) this._paramModel.getStartTime().clone(); 这样对startTime.a ...

  7. winform代码:关联窗体数据更新,删除dataGridview中选中的一行或多行

    一.关联窗体数据更新 关联窗体数据修改时,如果一个为总体数据显示窗体A,另一个为详细修改窗体B,从A进入B,在B中对数据进行修改,然后返回A,这时A窗体的数据需要更新. 我采用最简单的方法,首先保证每 ...

  8. 转: bower 客户端库管理工具

    概述 常用操作 库的安装 库的搜索和查看 库的更新和卸载 列出所有库 配置文件.bowerrc 库信息文件bower.json 相关链接 概述 注:bower下载安装依赖库实际上是使用git进行下载. ...

  9. linux下c/c++方式访问curl的帮助手册

    自:http://blog.chinaunix.net/u1/47395/showart_1768832.html 有个业务需求需要通过curl 代理的方式来访问外网 百度了一把,测试可以正常使用.记 ...

  10. HDU 2722 Here We Go(relians) Again

    最短路,建图太麻烦,略过…… #include <cstdio> #include <cstring> #include <queue> const int INF ...