最近两次比赛出现两道相同类型的题,有人十几分钟就AC了,而有人卡了俩小时。。。反思。。
先说hdu4353这道题,题意是要求一个从N个点1里边画出一个多边形来,然后给出M个点2。让这个(多边形的面积/多边形内点2的个数)最小。
描述很复杂。。。但是仔细想想会发现,多边形的点越多,面积也就越大,所以,这里只能画三个点,也就是一个三角形。至于怎么求点2的个数,这是很有必要总结的,祭奠我那苦逼的俩小时吧。。。。
先看一个图:
这不是立体图,仅仅是个平面图。。。
假设sum[i][j]表示i,j这条线上方这块区域的点的数目
可以看到三角形内点2的数目 = sum[i][j] + sum[j][k] - sum[i][k];
其实更通用一点就是: abs(sum[i][k] - sum[i][j] - sum[j][k]);
既然统计出这些点数来,这个问题基本就解决了。
HDU 4353的代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
const int N = 210; const int M = 511; struct Point { int x, y; bool operator < (const Point& cmp) const { return x < cmp.x; } }; Point a[N], b[M]; int sum[N][N]; int n, m; inline int det(int x1, int y1, int x2, int y2) { return x1*y2 - x2*y1; } inline int cross(Point a, Point b, Point c) { return det(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y); } int main() { //freopen("data.in", "r", stdin); int i, j, k, t, cas = 0, cnt; double ans, area; scanf("%d", &t); while(t--) { scanf("%d%d", &n, &m); REP(i, n) scanf("%d%d", &a[i].x, &a[i].y); REP(i, m) scanf("%d%d", &b[i].x, &b[i].y); sort(a, a + n); for(i = 0; i < n; ++i) { for(j = i + 1; j < n; ++j) { sum[i][j] = 0; for(k = 0; k < m; ++k) { if(b[k].x >= a[i].x && b[k].x < a[j].x) { if(cross(a[i], a[j], b[k]) > 0) sum[i][j]++; } } } } ans = -1; for(i = 0; i < n; ++i) { for(j = i + 1; j < n; ++j) { for(k = j + 1; k < n; ++k) { cnt = sum[i][k] - sum[i][j] - sum[j][k]; if(cnt == 0) continue; area = double(cross(a[i], a[j], a[k]))/2; if(ans == -1 || fabs(area/cnt) < ans) ans = fabs(area/cnt); } } } if(ans == -1) printf("Case #%d: -1\n", ++cas); else printf("Case #%d: %.6lf\n", ++cas, ans); } return 0; }
还有一个就是多校9上的1001题(HDU 4380)。比上面这个题更直白,需要统计三角形内的点数是不是奇数就可以。。。