1092 -- Farmland

  怎么最近做几何题都这么蛋疼,提交C++过不了交G++就过了。据我估计,原因是用了atan2这个函数,或者是其他一些函数造成了精度的影响。不管怎样,这题最后还是过了~

  解释一下题意,题目的意思是,给出一些边和点,要求找到简单多边形,也就是没有重复的点的多边形,而且多边形里面不能有其他的点。

  于是,还是之前的做法,对于每一条边作为起始边,从这条边出发,找最往左的一个点,然后移动到那里。不停这样的模拟,直到走回起始位置,就计算多边形是由多少条边构成的。如果满足就对计数器加一,最后输出结果即可。

最早通过的版本的写法是可以不用检查有没有点在多边形里面的:

 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <map> using namespace std; const int N = ;
struct Point {
int x, y;
Point() {}
Point(int x, int y) : x(x), y(y) {}
Point operator + (Point a) { return Point(x + a.x, y + a.y);}
Point operator - (Point a) { return Point(x - a.x, y - a.y);}
} pt[N]; typedef pair<int, int> PII;
typedef vector<Point> VPT;
typedef vector<int> VI; inline double angle(Point x) { return atan2((double) x.y, (double) x.x);}
inline int cross(Point x, Point y) { return x.x * y.y - x.y * y.x;} VI rel[N];
Point ori;
map<int, int> pid;
map<int, int> nx[N];
bool vis[N][N], vs[N];
int rec[N]; inline bool cmp(int a, int b) { return angle(pt[a] - ori) < angle(pt[b] - ori);}
double area() {
double ret = 0.0;
rec[rec[] + ] = rec[];
for (int i = ; i <= rec[]; i++) ret += cross(pt[rec[i]], pt[rec[i + ]]);
return ret / 2.0;
} int main() {
// freopen("in", "r", stdin);
// freopen("out", "w", stdout);
int T, n, k, x, id;
scanf("%d", &T);
while (T-- && ~scanf("%d", &n)) {
pid.clear();
for (int i = ; i < n; i++) {
scanf("%d", &id);
if (pid.find(id) == pid.end()) pid[id] = pid.size();
rel[pid[id]].clear();
nx[pid[id]].clear();
scanf("%d%d", &pt[pid[id]].x, &pt[pid[id]].y);
scanf("%d", &k);
while (k--) {
scanf("%d", &x);
if (pid.find(x) == pid.end()) pid[x] = pid.size();
rel[pid[id]].push_back(pid[x]);
}
}
// for (int i = 1; i <= n; i++) cout << i << ' ' << pid[i] << endl;
scanf("%d", &k);
for (int i = , sz; i <= n; i++) {
ori = pt[i];
sort(rel[i].begin(), rel[i].end(), cmp);
sz = rel[i].size();
if (sz <= ) continue;
rel[i].push_back(rel[i][]);
for (int j = ; j < sz; j++) nx[rel[i][j + ]][i] = rel[i][j];
rel[i].pop_back();
}
memset(vis, , sizeof(vis));
int cnt = ;
for (int i = , len, t; i <= n; i++) {
for (int j = , sz = rel[i].size(); j < sz; j++) {
memset(vs, , sizeof(vs));
rec[] = ;
int ls = i, cr = rel[i][j];
rec[++rec[]] = ls;
bool ok = true;
vs[cr] = true;
if (vis[ls][cr]) continue;
len = ;
// cout << "start " << i << ' ';
while (cr != i) {
rec[++rec[]] = cr;
// cout << cr << ' ';
t = cr;
cr = nx[ls][cr];
if (cr <= ) {
len = -;
break;
}
if (vs[cr]) ok = false;
vs[cr] = true;
ls = t;
vis[ls][cr] = true;
len++;
}
// cout << "~~" << len << endl;
if (ok && len == k && vs[nx[ls][cr]] && area() > 0.0) cnt++;
}
}
printf("%d\n", cnt);
}
return ;
}

  因为开始的时候wa太多次了,所以我的代码对标号重标号了。

然后不停的改啊改,最后改到把检查点在多边形内的操作也加上去了~

 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <map> using namespace std; const int N = ;
struct Point {
int x, y;
Point() {}
Point(int x, int y) : x(x), y(y) {}
Point operator + (Point a) { return Point(x + a.x, y + a.y);}
Point operator - (Point a) { return Point(x - a.x, y - a.y);}
} pt[N]; typedef pair<int, int> PII;
typedef vector<Point> VPT;
typedef vector<int> VI; inline double angle(Point x) { return atan2((double) x.y, (double) x.x);}
inline int cross(Point x, Point y) { return x.x * y.y - x.y * y.x;} VI rel[N];
Point ori;
map<int, int> pid;
map<int, int> nx[N];
bool vis[N][N], vs[N];
int rec[N]; inline bool cmp(int a, int b) { return angle(pt[a] - ori) < angle(pt[b] - ori);}
double area() {
double ret = 0.0;
rec[rec[] + ] = rec[];
for (int i = ; i <= rec[]; i++) ret += cross(pt[rec[i]], pt[rec[i + ]]);
return ret / 2.0;
} bool test(int p) {
int sz = rec[], wn = ;
rec[sz + ] = rec[];
for (int i = ; i <= sz; i++) {
if (pt[p].x == pt[rec[i]].x && pt[p].y == pt[rec[i]].y) return false;
int k = cross(pt[rec[i + ]] - pt[rec[i]], pt[p] - pt[rec[i]]);
int d1 = pt[rec[i]].y - pt[p].y;
int d2 = pt[rec[i + ]].y - pt[p].y;
if (k > && d1 <= && d2 > ) wn++;
if (k < && d2 <= && d1 > ) wn--;
}
return wn != ;
} bool check() {
// for (int i = 1; i <= rec[0]; i++) cout << rec[i] << ' '; cout << endl;
for (int i = , sz = pid.size(); i <= sz; i++) {
if (test(i)) return false;
}
return true;
} int main() {
// freopen("in", "r", stdin);
// freopen("out", "w", stdout);
int T, n, k, x, id;
scanf("%d", &T);
while (T-- && ~scanf("%d", &n)) {
pid.clear();
for (int i = ; i < n; i++) {
scanf("%d", &id);
if (pid.find(id) == pid.end()) pid[id] = pid.size();
rel[pid[id]].clear();
nx[pid[id]].clear();
scanf("%d%d", &pt[pid[id]].x, &pt[pid[id]].y);
scanf("%d", &k);
while (k--) {
scanf("%d", &x);
if (pid.find(x) == pid.end()) pid[x] = pid.size();
rel[pid[id]].push_back(pid[x]);
}
}
// for (int i = 1; i <= n; i++) cout << i << ' ' << pid[i] << endl;
scanf("%d", &k);
if (k < ) { puts(""); continue;}
for (int i = , sz; i <= n; i++) {
ori = pt[i];
sort(rel[i].begin(), rel[i].end(), cmp);
sz = rel[i].size();
if (sz <= ) continue;
rel[i].push_back(rel[i][]);
for (int j = ; j < sz; j++) nx[rel[i][j + ]][i] = rel[i][j];
rel[i].pop_back();
}
memset(vis, , sizeof(vis));
int cnt = ;
for (int i = , len, t; i <= n; i++) {
for (int j = , sz = rel[i].size(); j < sz; j++) {
rec[] = ;
int ls = i, cr = rel[i][j];
if (vis[ls][cr]) continue;
vis[ls][cr] = true;
bool ok = true;
memset(vs, , sizeof(vs));
len = ;
// cout << "start " << i << ' ';
while (nx[ls][cr]) {
rec[++rec[]] = cr;
// cout << cr << ' ';
t = cr;
cr = nx[ls][cr];
if (cr <= ) {
len = -;
break;
}
if (vs[cr]) ok = false;
vs[cr] = true;
ls = t;
if (vis[ls][cr]) break;
vis[ls][cr] = true;
len++;
}
// cout << "~~" << len << endl;
if (ok && len == k && ls == i && area() >= 1e- && check()) cnt++;
}
}
printf("%d\n", cnt);
}
return ;
}

——written by Lyon

poj 1092 Farmland (Geometry)的更多相关文章

  1. poj 1039 Pipe (Geometry)

    1039 -- Pipe 理解错题意一个晚上._(:з」∠)_ 题意很容易看懂,就是要求你求出从外面射进一根管子的射线,最远可以射到哪里. 正解的做法是,选择上点和下点各一个,然后对于每个折点位置竖直 ...

  2. POJ题目排序的Java程序

    POJ 排序的思想就是根据选取范围的题目的totalSubmittedNumber和totalAcceptedNumber计算一个avgAcceptRate. 每一道题都有一个value,value ...

  3. POJ 2240 Arbitrage / ZOJ 1092 Arbitrage / HDU 1217 Arbitrage / SPOJ Arbitrage(图论,环)

    POJ 2240 Arbitrage / ZOJ 1092 Arbitrage / HDU 1217 Arbitrage / SPOJ Arbitrage(图论,环) Description Arbi ...

  4. poj 1556 (Dijkstra + Geometry 线段相交)

    链接:http://poj.org/problem?id=1556 The Doors Time Limit: 1000MS   Memory Limit: 10000K Total Submissi ...

  5. poj 1066 Treasure Hunt (Geometry + BFS)

    1066 -- Treasure Hunt 题意是,在一个金字塔中有一个宝藏,金字塔里面有很多的墙,要穿过墙壁才能进入到宝藏所在的地方.可是因为某些原因,只能在两个墙壁的交点连线的中点穿过墙壁.问最少 ...

  6. poj 1689 && zoj 1422 3002 Rubbery (Geometry + BFS)

    ZOJ :: Problems :: Show Problem 1689 -- 3002 Rubbery 这题是从校内oj的几何分类里面找到的. 题意不难,就是给出一个区域(L,W),这个区域里面有很 ...

  7. poj 1263 Reflections (Simple Geometry)

    1263 -- Reflections 简单计算几何.题目给出射线以及若干个不相交的圆,求出射线会在哪些圆上反弹,依次写出反弹球的编号. 代码如下: #include <cstdio> # ...

  8. poj 3334 Connected Gheeves (Geometry + BInary Search)

    3334 -- Connected Gheeves 题意是,给出两个尖形的相连的容器,要求向其中灌水.它们具有日常的物理属性,例如两个容器中水平面高度相同以及水高于容器顶部的时候就会溢出.开始的时候打 ...

  9. POJ题目细究

    acm之pku题目分类 对ACM有兴趣的同学们可以看看 DP:  1011   NTA                 简单题  1013   Great Equipment     简单题  102 ...

随机推荐

  1. JSP内置对象解析

    out对象:(PrintWriter类的实例) 用来向客户端输出信息,除了输出各种信息外还负责对缓冲区进行管理: 主要方法: print / println void 输出数据 newLine() v ...

  2. windows 环境下搭建docker私有仓库

    windows 环境下搭建docker私有仓库 1.在公用仓库中pull仓库镜像 docker pull regitry 2.启动仓库镜像 //-d意思是后台运行,-p是做端口映射,这里是将本地的50 ...

  3. python基础--GIL全局解释器锁、Event事件、信号量、死锁、递归锁

    ps:python解释器有很多种,最常见的就是C python解释器 GIL全局解释器锁: GIL本质上是一把互斥锁:将并发变成串行,牺牲效率保证了数据的安全 用来阻止同一个进程下的多个线程的同时执行 ...

  4. Leetcode628.Maximum Product of Three Numbers三个数的最大乘积

    给定一个整型数组,在数组中找出由三个数组成的最大乘积,并输出这个乘积. 示例 1: 输入: [1,2,3] 输出: 6 示例 2: 输入: [1,2,3,4] 输出: 24 注意: 给定的整型数组长度 ...

  5. 威胁快报|Nexus Repository Manager 3新漏洞已被用于挖矿木马传播,建议用户尽快修复

    背景 近日,阿里云安全监测到watchbog挖矿木马使用新曝光的Nexus Repository Manager 3远程代码执行漏洞(CVE-2019-7238)进行攻击并挖矿的事件. 值得注意的是, ...

  6. Django用户名密码错误提示

    from django.shortcuts import render # Create your views here. from django.shortcuts import render fr ...

  7. nginx反项代理的简单配置

    在ubuntu 16.04下安装nginx, apt-get install nginx就可以了. 然后安装了node, npm, 写了个简单的main.js,启动了一个http,并监听 8888 然 ...

  8. JavaScript 生成32位UUID

    function uuid(){ var len=32; //32长度 var radix=16; //16进制 var chars='0123456789ABCDEFGHIJKLMNOPQRSTUV ...

  9. KNN最近邻算法

    算法概述 K最近邻(K-Nearest Neighbor,KNN)算法,是著名的模式识别统计学方法,在机器学习分类算法中占有相当大的地位.它是一个理论上比较成熟的方法.既是最简单的机器学习算法之一,也 ...

  10. 读JS高性能总结——DOM编程(一)

    DOM是一个与语言无关的API,它在浏览器中的借口却是用JS来实现的. 浏览器通常会把DOM和JS独立实现. 在IE中,JS的实现名是JScript,位于jscript.dll文件中,DOM实现则是m ...