题意:给定一个跳蚤位置和移动方向,现在在一个国际象棋棋盘上,左下角为黑格,一个格子为s*s,判断能否移动到白格子,问要移动多少次才能到白格,边界不算白格。
思路:利用鸽笼原理落在黑格子和边界上的一共有(s + 1)^2个点,也就是说,如果形成循环,周期肯定在这之内,所以可以不断去模拟跳格子,直到踩到白格,或者踩到之前落到过的黑格就结束
不过其实还有更优的方法,因为跳蚤跳跃路径为直线,观察下可以发现如果可以到白格,最多连成一条小于(2 x 2)格子对角线长度的线,那么上面一共有不超过2 * s个黑点,于是其实只需要判断前2s步能不能到白格就可以了,如果不能,说明必然中间形成了周期,也就是始终到不了白格了
代码:
原来的:
#include <stdio.h> #include <string.h> const int N = 1005; bool vis[N][N]; long long s, x, y, dx, dy; bool white() { if (x % s == 0 || y % s == 0) return false; if (((x / s)&1)^((y / s)&1)) return true; return false; } bool in() { if (x > s || y > s) { x -= s; y -= s; if (x < 0) x = s; if (y < 0) y = s; } if (vis[x][y]) return false; vis[x][y] = true; return true; } int main() { while (~scanf("%lld%lld%lld%lld%lld", &s, &x, &y, &dx, &dy) && s) { memset(vis, false, sizeof(vis)); long long ans = 0, ansx = x, ansy = y; while (1) { x %= 2 * s; y %= 2 * s; if (white()) { printf("After %lld jumps the flea lands at (%lld, %lld).\n", ans, ansx, ansy); break; } if (!in()) { printf("The flea cannot escape from black squares.\n"); break; } x += dx; y += dy; ansx += dx; ansy += dy; ans++; } } return 0; }
简化后的:
#include <stdio.h> #include <string.h> long long s, x, y, dx, dy; bool judge(long long x, long long y) { return (x % s && y % s && (x / s + y / s) % 2); } int main() { while (~scanf("%lld%lld%lld%lld%lld", &s, &x, &y, &dx, &dy) && s) { int i; for (i = 0; i < 2 * s; i++) { if (judge(x, y)) { printf("After %d jumps the flea lands at (%lld, %lld).\n",i,x,y); break; } x += dx; y += dy; } if (i == 2 * s) printf("The flea cannot escape from black squares.\n"); } return 0; }
UVA 10620 - A Flea on a Chessboard(鸽笼原理),布布扣,bubuko.com
UVA 10620 - A Flea on a Chessboard(鸽笼原理)
原文:http://blog.csdn.net/accelerator_/article/details/36866095