Problem
【AMPPZ2014】Pillars
Time Limit: 5Sec
Memory Limit: 256MB
SpecialJudge
Description
给定一个n×m的矩形,其中有f个2×2的障碍物,其中任意两个障碍物中心之间的欧几里得距离至少为6,
且每个障碍物的中心到边缘的距离至少为3。请找到一条从左下角(1,1)出发经过所有没有障碍物的点各一次的且最后回到左下角的回路。
第一行包含三个整数n,m,f(1≤n,m≤1000且n,m都为偶数)。
接下来f行,每行两个整数x,y(1≤x<n, 1≤y<m),表示该障碍物左下角的坐标。
Output
如果无解,输出NIE,否则第一行输出TAK,第二行输出方案。
方案包含n×m−4×f个字符,第i个字符表示第i步的移动方向,用G表示上,D表示下,L表示左,P表示右。
Sample Output
1 2
| TAK PPPPPPPPPPPGGGLDDLLLLLGPPGLLLDDLLLGGGPPPPPPPPPPGLLLLLLLLLLLDDDDD
|
Hint
![](http://www.lydsy.com/JudgeOnline/upload/201506/PillarsSample.JPG)
标签:构造
Solution
一道很适合构造入门的题。
我看了Claris的题解才想出来。
首先不考虑障碍,构造出一个走过全部格子的走法。由于n和m均为偶数,一定有解。
然后考虑障碍,对障碍四周的格子的方向进行修改。由于两个障碍间距离至少为3,故任两个障碍不会影响,只会有两大类。
具体构造方法参见代码。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include <bits/stdc++.h> #define MAX_N 1000 using namespace std; int n, m, f; char s[MAX_N+5][MAX_N+5]; int main() { scanf("%d%d%d", &n, &m, &f); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) s[i][j] = i&1 ? 'D' : 'G'; for (int i = 1; i <= n; i++) { if (i^n) s[i][1] = 'P'; if ((i^1) && (i&1)) s[i][2] = 'L'; if (!(i&1)) s[i][m] = 'L'; } for (int i = 0; i < f; i++) { int x, y; scanf("%d%d", &x, &y); if (x&1) s[x][y+2] = 'P', s[x+1][y-1] = 'L', s[x+1][y+2] = 'P', s[x+2][y+3] = 'L'; else if (y^3) s[x][y-1] = 'P', s[x+1][y-1] = 'P', s[x+1][y+2] = 'L', s[x+2][y-2] = 'L'; else s[x][1] = 'G', s[x][2] = 'P', s[x+1][2] = 'D', s[x+1][5] = 'L'; } puts("TAK"); for (int x = 1, y = 1, lft = n*m-4*f; lft; lft--) { putchar(s[x][y]); if (s[x][y] == 'P') x++; else if (s[x][y] == 'L') x--; else if (s[x][y] == 'G') y++; else y--; } return 0; }
|