CodeForces - 659D 模拟

题意

你正在沿着指定路线<数据保证起点位于路线的最左下方><路线只包括横纵两种方向并且一定先向北开>,绕湖练车<跑一圈>,但是呢你有点困,你就可能掉进湖里,问,你可能掉进湖里的点(假设开疲劳驾驶可以开直线~~)有多少

模拟解法:

显然,人类能看到面前是湖的时候才可能径直走下去。建立地图时把给的点离散化,然后就可以在给定内存内完成工作了。

为了保证两条路储存时不相邻(保证湖的连通性),这里离散化时把每个点的x,y都变成正常离散后的二倍,即可。、

通过他给的路线,把路径画出来,然后DFS把里面的湖用2标记,再分类判断。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<set>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
typedef long long ll;
typedef int anytype;
int x[1005];
int y[1005];
int xx, yy;
struct Node {
	int x, y;
};
Node way[1005];
int map[2005][2005];
int n;
void d() {
	sort(x, x + n);
	sort(y, y + n);
	xx = unique(x, x + n) - x;
	yy = unique(y, y + n) - y;
}
void find(int &a, int &b) {
	a = 2 * (lower_bound(x, x + xx, a) - x) + 1;
	b = 2 * (lower_bound(y, y + yy, b) - y) + 1;
}
int dx[] = { 0,0,1,-1 };
int dy[] = { 1,-1,0,0 };
void dfs(int i, int j) {
	if (map[i][j] != 0)return;
	map[i][j] = 2;
	for (int t = 0; t < 4; t++)dfs(i + dx[t], j + dy[t]);
}
void init() {
	int ans = 0;
	for (int i = 0; i <= n; i++) {
		find(way[i].x, way[i].y);
	}
	for (int i = 1; i <= n; i++) {
		if (way[i - 1].x == way[i].x) {
			if (way[i - 1].y > way[i].y) {
				for (int j = way[i].y; j <= way[i-1].y; j++) {
					map[way[i].x][j] = 1;
				}
			}
			else {
				for (int j = way[i].y; j >= way[i-1].y; j--) {
					map[way[i].x][j] = 1;
				}
			}
		}
		else {
			if (way[i - 1].x > way[i].x) {
				for (int j = way[i].x; j <= way[i-1].x; j++) {
					map[j][way[i].y] = 1;
				}
			}
			else {
				for (int j = way[i].x; j >= way[i-1].x; j--) {
					map[j][way[i].y] = 1;
				}
			}
		}
	}
	dfs(way[0].x + 1, way[0].y + 1);
	for (int i = 1; i <= n; i++) {
		if (way[i].y == 0)continue;
		if (way[i - 1].x == way[i].x) {
			if (way[i - 1].y > way[i].y) {//d
				if (map[way[i].x][way[i].y - 1] != 0) {
					++ans;//cout<<x[way[i].x]<<" "<<y[way[i].y]<<endl;;
				}
			}
			else {//u
				if (map[way[i].x][way[i].y + 1] != 0) {
					++ans;//cout<<x[way[i].x]<<" "<<y[way[i].y]<<endl;;
				}
			}
		}
		else {
			if (way[i - 1].x > way[i].x) {//l
				if (way[i].x == 0)continue;
				if (map[way[i].x - 1][way[i].y] != 0) {
					++ans;//cout<<x[way[i].x]<<" "<<y[way[i].y]<<endl;;
				}
			}
			else {//r
				if (map[way[i].x + 1][way[i].y] != 0) {
					++ans;//cout<<x[way[i].x]<<" "<<y[way[i].y]<<endl;;
				}
			}
		}
	}
	printf("%d", ans);
}
int main() {
	scanf("%d", &n);
	for (int i = 0; i <= n; i++) {
		scanf("%d%d", &x[i], &y[i]);
		way[i].x = x[i];
		way[i].y = y[i];
	}
	d();
	init();

}

正解:

画出图,可以发现你总体上是顺时针绕了一圈,途中逆时针拐弯的点会可能掉下去。每个点判断一下顺时针还是逆时针就OK。

可以分类讨论,用多边形内角和公式,向量外积等方法

/*思路:
因为是直角拐弯,所以内角要么是90度,要么是270度,设270的角的个数为x,则可得方程180*(n - 2) = 270 * x + (n - x) * 90;
化简得:x = (n - 4) / 2;*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#define INF 0x3f3f3f3f
#define ull unsigned long long
#define ll long long
#define IN __int64
#define N 100010
#define M 1000000007
using namespace std;
struct zz{
	int x;
	int y;
}p[N];
int main(){
	int t, n, m, i, j, k;
	while (scanf("%d", &n) != EOF){
		for (i = 0; i <= n; i++)
			scanf("%d%d", &p[i].x, &p[i].y);
		printf("%d\n", (n - 4) / 2);
	}
	return 0;
}
//向量积
#include <cstdio>
#include <algorithm>
 
using namespace std;
 
typedef long long LL;
typedef pair<int, int> pii;
 
const int maxn = 1005;
 
int n;
pii p[maxn];
 
int main() {
	scanf("%d", &n);
	for(int i = 1; i <= n + 1; i++) scanf("%d%d", &p[i].first, &p[i].second);
	p[0] = p[n];
 
	int ans = 0;
	for(int i = 1; i <= n; i++) {
		int x1 = p[i - 1].first, y1 = p[i - 1].second;
		int x2 = p[i].first, y2 = p[i].second;
		int x3 = p[i + 1].first, y3 = p[i + 1].second;
		LL costh = (x2 - x1) * (y3 - y2) - (x3 - x2) * (y2 - y1);
		if(costh > 0) ans++;
	}
 
	printf("%d\n", ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41104612/article/details/81154949