洛谷 P6200 题解

推销一下我的新博客:https://yce3216037.github.io/post/luo-gu-p6200-ti-jie/

这道题就是一道水题,就是说有多少个点,使得在它的正北,正南,正东,正西,东北,东南,西北,西南和该点所连的直线能覆盖所有点,直接枚举每一个点,然后看一下这个点是否合法即可,时间复杂度为 O(n3)O(n^3)

代码如下:

#include<cstdio>
using namespace std;
const int N = 100 + 10;
FILE *fin, *fout;
inline int read(int &x) {
	char c = 0; int f = x = 0;
	while (c < 48 || c > 57) {
		if (c == -1) return 0;
		if (c == '-') f = 1; c = fgetc(fin);
	}
	while (c > 47 && c < 58) x = (x << 3) + (x << 1) + (c & 15), c = fgetc(fin);
	if (f) x = -x; return 1;
}
template<class T, class... Args> inline int read(T &x, Args&... args) {
	return read(x) + read(args...);
}
inline int write(int x) {
	if (x < 0) return fputc(45, fout), write(-x);
	if (x > 9) write(x / 10);
	return fputc((x % 10) | 48, fout), 1;
}
int n, k, x, y, ans, vis[N][N];//vis[i][j]表示第i行第j列的位置有几个对手
inline void work(int x, int y) {
	int res = vis[x][y], temp = vis[x][y]; vis[x][y] = 0;//这个地方的vis[x][y]要先清零,否则可能会被算多次
	for (int i = 1; i <= n; ++i) res += vis[x][i];
	for (int i = 1; i <= n; ++i) res += vis[i][y];
	for (int i = x + 1, j = y + 1; i <= n && j <= n; ++i, ++j) res += vis[i][j];
	for (int i = x - 1, j = y + 1; i && j <= n; --i, ++j) res += vis[i][j];
	for (int i = x - 1, j = y - 1; i && j; --i, --j) res += vis[i][j];
	for (int i = x + 1, j = y - 1; i <= n && j; ++i, --j) res += vis[i][j];
    //8个方向的对手数量
	if (res == k) ++ans; vis[x][y] = temp;//别忘记加回来
}
int main() {
	#ifdef ONLINE_JUDGE
	fin = stdin;
	fout = stdout;
	#else
	fin = fopen("P6200.in", "rb");
	fout = fopen("P6200.out", "wb");
	#endif
	read(n, k);
	for (int i = 1; i <= k; ++i) read(x, y), ++vis[x][y];
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= n; ++j)
			work(i, j);//枚举每一个点即可
	write(ans);
	return 0;
}