题意
你正在沿着指定路线<数据保证起点位于路线的最左下方><路线只包括横纵两种方向并且一定先向北开>,绕湖练车<跑一圈>,但是呢你有点困,你就可能掉进湖里,问,你可能掉进湖里的点(假设开疲劳驾驶可以开直线~~)有多少
模拟解法:
显然,人类能看到面前是湖的时候才可能径直走下去。建立地图时把给的点离散化,然后就可以在给定内存内完成工作了。
为了保证两条路储存时不相邻(保证湖的连通性),这里离散化时把每个点的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;
}