这道题如果直接用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 支付宝钱包手势password裂纹战斗

    底 随着移动互联网和手机屏幕越做越大的普及等..购物在移动设备上.消费是必不可少的人们习惯于生活. 随着这股浪潮的兴起,安全.便捷的移动支付的需求也越来越大.故,各大互联网公司纷纷推出了移动支付平台. ...

  2. Cocos2d-X 动作展示《一》

    因为Cocos2d-X中的动作较多,我将全部的动作制作成了一个滚动视图.每一个滚动视图上都有动作名,单击滚动视图就能够展示对应的动作 程序效果图: 使用滚动视图实现动作切换 动作展示 程序代码: 首先 ...

  3. objective-C学习笔记(八) 集合类型 Collection Types

    OBJC的集合类型: 1.数组 Array 2.Set 3.键值对 Dictionary 数组:OC中的数组被定义为class,引用类型.索引从0开始,访问越界会抛出运行时异常. NSArray的元素 ...

  4. The Painter's Partition Problem Part II

    (http://leetcode.com/2011/04/the-painters-partition-problem-part-ii.html) This is Part II of the art ...

  5. HDOJ 1166.敌兵布阵

    2015-06-08 问题简述: 原题的题意相当于有一些连续摆放的箱子,里面装着球,球的数量可以加减,现要查询几个连续的箱子里球的总数,其中存在放球和拿球的操作. 原题链接:http://acm.hd ...

  6. Webx pull service

    1.概述 pull service的功能是将对象置入模板中.被pull service放到模板中的对象,不需要应用程序的干预即可直接使用.如果模板没有用到某个对象,则不会产生创建该对象的开销.看起来, ...

  7. java json的处理

    maven依赖 <dependencies> <dependency> <groupId>com.alibaba</groupId> <artif ...

  8. android开发环境安装记录

    首先进入http://developer.android.com/sdk/index.html, Google提供了一个新的DeveloperTools,即:ADT Bundle,中文翻译之:ADT捆 ...

  9. js 中的bind函数

    bind是Function.prototype中内置函数 作用是指定函数作用域 代码参考 http://blog.csdn.net/load_life/article/details/7200381 ...

  10. 干I​n​l​a​y​的​生​产​过​程​

    •天线的组成 天线的材料有0.38PET和0.16以及0.3的铝箔组成. 倒封装 •将IC倒装在天线焊盘位置. •方法:先点胶水, 然后把IC对准焊盘(IC一面有凸点),通过热压把IC 固定在焊盘上. ...