poj 1092 Farmland (Geometry)
怎么最近做几何题都这么蛋疼,提交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)的更多相关文章
- poj 1039 Pipe (Geometry)
1039 -- Pipe 理解错题意一个晚上._(:з」∠)_ 题意很容易看懂,就是要求你求出从外面射进一根管子的射线,最远可以射到哪里. 正解的做法是,选择上点和下点各一个,然后对于每个折点位置竖直 ...
- POJ题目排序的Java程序
POJ 排序的思想就是根据选取范围的题目的totalSubmittedNumber和totalAcceptedNumber计算一个avgAcceptRate. 每一道题都有一个value,value ...
- POJ 2240 Arbitrage / ZOJ 1092 Arbitrage / HDU 1217 Arbitrage / SPOJ Arbitrage(图论,环)
POJ 2240 Arbitrage / ZOJ 1092 Arbitrage / HDU 1217 Arbitrage / SPOJ Arbitrage(图论,环) Description Arbi ...
- poj 1556 (Dijkstra + Geometry 线段相交)
链接:http://poj.org/problem?id=1556 The Doors Time Limit: 1000MS Memory Limit: 10000K Total Submissi ...
- poj 1066 Treasure Hunt (Geometry + BFS)
1066 -- Treasure Hunt 题意是,在一个金字塔中有一个宝藏,金字塔里面有很多的墙,要穿过墙壁才能进入到宝藏所在的地方.可是因为某些原因,只能在两个墙壁的交点连线的中点穿过墙壁.问最少 ...
- poj 1689 && zoj 1422 3002 Rubbery (Geometry + BFS)
ZOJ :: Problems :: Show Problem 1689 -- 3002 Rubbery 这题是从校内oj的几何分类里面找到的. 题意不难,就是给出一个区域(L,W),这个区域里面有很 ...
- poj 1263 Reflections (Simple Geometry)
1263 -- Reflections 简单计算几何.题目给出射线以及若干个不相交的圆,求出射线会在哪些圆上反弹,依次写出反弹球的编号. 代码如下: #include <cstdio> # ...
- poj 3334 Connected Gheeves (Geometry + BInary Search)
3334 -- Connected Gheeves 题意是,给出两个尖形的相连的容器,要求向其中灌水.它们具有日常的物理属性,例如两个容器中水平面高度相同以及水高于容器顶部的时候就会溢出.开始的时候打 ...
- POJ题目细究
acm之pku题目分类 对ACM有兴趣的同学们可以看看 DP: 1011 NTA 简单题 1013 Great Equipment 简单题 102 ...
随机推荐
- pytorch 常用问题解决
1.RuntimeError: cuda runtime erorr (77): an illegal memory access was encountered at 在使用命令前面加上CUDA_L ...
- 洛谷P1006 NOIP提高组2008 传纸条
P1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n 列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无 ...
- UnicodeEncodeError:'latin-1' codec can't encode characters in position 0-1: ordinal not in range(256) Scrapy
1.使用scrapy对数据进行入库时,出现如下错误: UnicodeEncodeError:'latin-1' codec can't encode characters in position 0- ...
- Django项目:CRM(客户关系管理系统)--13--05PerfectCRM实现King_admin注册功能获取内存02
admin_class.model = modelself.registered_sites[app_name][model_name] = admin_class #注册APP #base_admi ...
- NodeJS概述2-事件插件-简易爬虫
事件 events 模块 原生事件写法 /* * 1. 事件分类 * DOM0级 事件 - on + eventType * DOM2级 事件 - 事件监听 * 2. 事件构成部分有哪些? dom.o ...
- HTML小技巧:按钮中的文字换行 .
一般按钮的文字都是一行的.但是有的时候画面需要按钮中的文字换行. 刚开始有个开发人员说没法实现.\r\n 都用过了没有效果.其实google这个老师是非常强大的. 直接换行的方法:<input ...
- Leetcode925.Long Pressed Name长按键入
你的朋友正在使用键盘输入他的名字 name.偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次. 你将会检查键盘输入的字符 typed.如果它对应的可能是你的朋友的名字(其中一 ...
- 【JZOJ4804】【NOIP2016提高A组模拟9.28】成绩调研
题目描述 输入 输出 样例输入 5 3 1 2 3 1 2 1 2 1 1 1 1 样例输出 4 数据范围 解法 考虑设置左指针l和右指针r: 维护[l,r]的关于等第的桶. 初始l=r=0: 每次右 ...
- 【JZOJ4771】【NOIP2016提高A组模拟9.9】爬山
题目描述 国家一级爬山运动员h10今天获得了一张有着密密麻麻标记的地图,在好奇心的驱使下,他又踏上了去爬山的路. 对于爬山,h10有一个原则,那就是不走回头路,于是他把地图上的所有边都标记成了有向边. ...
- jmeter测试APP时如何录制脚本
jmeter录制脚本需要注意的点: (1)手机和电脑需要处于一个局域网内(如手机和电脑所使用一个wifi) (2)设置手机代理的时候手机IP填写本机IP,端口号要和jmeter的相同,一般情况下端口号 ...