UVa 225 Golygons 题解

Posted alrond

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVa 225 Golygons 题解相关的知识,希望对你有一定的参考价值。

难度:β

建议用时:40 min

 

关于这道题目的背景在维基百科上有。很神奇。

 

但是我们的这道题没有那么多考虑。上来直接东南西北狂搜一通就好了。

算法很简单,直接上过程。

 

首先确定 “东”“南”“西”“北” 对应的英文字母 “e”“s”“w”“n”。

因为题目还说不能后退,所以要把后退的方向也处理出来。”东“对”西“ 等等。

 

因为出发点在(0,0),又可以往负的方向走,为了用数组存,我们给每个坐标加一个 buf = 105 的东西,保证坐标都非负。

1 blocks[x+buf][y+buf] = 1;

 

另外因为对一个方向最多只走 buf 个距离,因此在范围外的障碍物就 pass 掉。

1 if(abs(x) > buf || abs(y) > buf) continue;

 

下面直接东南西北搜。

技术分享图片
 1 void dfs(int curDepth, int curX, int curY, int lastDir) {
 2     if(curDepth == lastLenth) {
 3         if(curX == startX && curY == startY) {
 4             output();
 5             total++;
 6         }
 7         return;
 8     }
 9     
10     if(is_time_to_go_back(curDepth, curX, curY)) return;
11     
12     for(int dir = 0; dir <= 3; dir++) {
13         int newX = curX + dx[dir]*(curDepth+1);
14         int newY = curY + dy[dir]*(curDepth+1);
15         
16         if(abs(newX) > buf || abs(newY) > buf) continue;
17         if(block_in_the_way(curX, curY, newX, newY)) continue;
18         if(dir + lastDir == 3 || dir == lastDir) continue;
19         if(vis[newX+buf][newY+buf]) continue;
20         
21         vis[newX+buf][newY+buf] = 1;
22         path[curDepth] = dir;
23         dfs(curDepth+1, newX, newY, dir);
24         vis[newX+buf][newY+buf] = 0;
25     }
26 }
View Code

 

注意这里的细节:

1 if(dir + lastDir == 3 || dir == lastDir) continue;

 

回头看:

1 const char directions[] = {e, n, s, w};

 

哦!好妙!判断方向方便很多!小技巧。

 

作为一到剪枝题,这里的重点就在剪枝函数 “is_time_to_go_back” 上。

先分析一下。要想在规定的步数走回原点,容易想到要限制不能走太远。因为走的距离和是有限的。而这里的距离是以曼哈顿距离为参考的。所以自然要在这方面剪枝。

1 bool is_time_to_go_back(int curDepth, int curX, int curY) {
2     int manhattan_dist = abs(curX) + abs(curY);
3     int remain_dist = S[lastLenth] - S[curDepth];
4     if(remain_dist < manhattan_dist) return true;
5     return false;
6 }

这个 “S” 就是等差数列前 n 项和。计算出还可以走多少曼哈顿距离。

构造 “S” :

1 void init() {
2     S[0] = 0;
3     for(int i = 1; i <= 20; i++) S[i] = S[i-1] + i;
4 }

 

 

这题还需判断有没有障碍物,上 code :

bool block_in_the_way(int sx, int sy, int tx, int ty) {
    if(sx > tx) swap(sx, tx);
    if(sy > ty) swap(sy, ty);
    for(int x = sx; x <= tx; x++) {
        for(int y = sy; y <= ty; y++) {
            if(blocks[x+buf][y+buf]) return true;
        }
    }
    return false;
}

 

大概想法就是枚举路上的每一个点,判断是不是障碍物。

注意要保证 x 和 y 的递增。否则枚举会出问题。

 

总体过程结束了。

这题回头看没有什么难点,曼哈顿距离就是求绝对值之和。不知道还有没有更高效的剪枝方法。

 

不明白的请留言。

 

如果你对这篇文章感兴趣,请关注我,我会定期(每天)更新文章。希望一起交流哈~

2018-01-22 00:02:04 (好晚啊)

以上是关于UVa 225 Golygons 题解的主要内容,如果未能解决你的问题,请参考以下文章

UVa225 Golygons (DFS)

题解Street Numbers [UVA138]

RQNOJ 225 [JSOI2007]书本整理 题解

UVa 307 Sticks 题解

题解 UVa11727

题解 UVa13244