这道题如果直接用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. The Linux device model

    /sys和 /dev的疑问 1./dev 下放的是设备文件,是由应用层mknod创建的文件.假设底层驱动对mknod的设备号有相应的驱动,如open等函数.那么应用层open "/dev/* ...

  2. 在Attribute Inspector 上显示自定义的控件的属性

    FirstColor 跟 CornerRadious 都是新增的显示属性具体实现方法如下: @property(nonatomic,weak)IBInspectable UIColor *firstC ...

  3. ACM比赛

    Description A soldier wants to buy w bananas in the shop. He has to pay k dollars for the first bana ...

  4. 51NOD 算法马拉松8

    题目戳这里:51NOD算法马拉松8 某天晚上kpm在玩OSU!之余让我看一下B题...然后我就被坑进了51Nod... A.还是01串 水题..怎么乱写应该都可以.记个前缀和然后枚举就行了.时间复杂度 ...

  5. C++的常量折叠(二)

    前面的C++的常量折叠(一)的最后留下了一个问题,那就是在声明i的时候,加上修饰符volatile关键字,发现结果输出的就不一样了,下面来说一下volatile这个关键字. C/C++中的volati ...

  6. [LeetCode]题解(python):072-Edit Distance

    题目来源: https://leetcode.com/problems/edit-distance/ 题意分析: word1最少通过多少步可以变成word2.word1只能进行一下的操作.a)插入一个 ...

  7. windows server 2008/2012 无法安装AD域解决方法记录

    安装活动目录之前需要一些准备工作和前提条件的. 有管理员的权限 至少有一个足够大的NTFS文件系统的分区或动态卷 需要DNS服务配合,因此需要安装DNS服务 最好使用dcpromo命令来进行安装 最终 ...

  8. Oracle 11g透明网关连接Sqlserver 2000

    一.环境 公司网站系统使用的是IIS + Oracle 但公司某系统使用的是Sqlserver 2000, 但其数据需要做成报表放到网站上,为简化编程,使用Oracle做透明网关,定期从Sqlserv ...

  9. HDU 1849 Rabbit and Grass

    题解:因为棋子可重叠,所以就等于取石子问题,即尼姆博弈,SG[i]=i,直接将输入数据异或即可. #include <cstdio> int main(){ int SG,n,a; whi ...

  10. JAVA GUI学习 - JFileChooser文件选择器组件学习:未包括JFileChooser系统类学习

    public class JFileChooserKnow { /** * @param args */ public static void main(String[] args) { // TOD ...