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 ...
随机推荐
- MVC的学习步骤
(1)搭建环境(2)如何完成Controller和 Model的映射(3)如何把值传给Controller(4)Controller如何把值传给viewer(5)异常处理(6)页面标签(7)文件上传( ...
- day18 12.丢失更新介绍与悲观锁
共享锁在一条记录上是可以加多个的,共享嘛.排它锁的意思是指这条记录上如果有任何其他的锁我排它锁是加不上的,有了排它锁其他锁也是加不上的,唯一的.比如说现在我的记录上没锁,加了排它锁其他人使用不了,我这 ...
- sql server 创建视图添加表时出现从其他数据库导入的表未显示出来
创建视图添加表时出现从其他数据库导入的表未显示出来,通过数据库刷新,也不能解决.关闭SQL server management studio 后,再次进入,在创建视图的时候添加表的列表就出现了新导入的 ...
- 2016年中国独角兽企业估值榜 TOP300
2016年中国独角兽企业估值榜 TOP300[完整榜单] 类型:品牌资讯/名企动态 阅读:6735次 来源: 中商情报网 我要评论 摘要:独角兽公司是什么?独角兽公司指的是那些估值达到10亿美元以 ...
- JSP Web第七章整理复习 Servlet基础知识
P206-208 Servlet项目的创建,web.xml的配置及标签含义,相关程序 创建:new 一个Servlet类,继承自javax.servlet.http.HttpServlet; 写doG ...
- 洛谷P1541 乌龟棋 [2010NOIP提高组]
P1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家 ...
- Amazon Redshift数据迁移到MaxCompute
Amazon Redshift数据迁移到MaxCompute Amazon Redshift 中的数据迁移到MaxCompute中经常需要先卸载到S3中,再到阿里云对象存储OSS中,大数据计算服务Ma ...
- golang数据类型二
字符类型 3.14基本数据类型的相互转换 3.15基本数据类型和string的转换 FormatInt // FormatUint 将 int 型整数 i 转换为字符串形式// base:进位制(2 ...
- 编程语言分类及python所属类型
编程语言分类及python所属类型 编程语言主要从以下几个角度为进行分类:编译型和解释型.静态语言和动态语言.强类型定义语言和弱类型定义语言. 编译和解释的区别是什么? 编译器是把源程序的每一条语句都 ...
- 【时光回溯】【JZOJ3566】【GDKOI2014】阶乘
题目描述 输入 第一行有一个正整数T,表示测试数据的组数. 接下来的T行,每行输入两个十进制整数n和base. 输出 对于每组数据,输出一个十进制整数,表示在base进制下,n!结尾的零的个数. 样例 ...