HDU 4380 Farmer Greedy
题意: 知道了n 个房子的坐标,和m 个金矿的坐标,问可以选出多少个三个房子,使得这三个房子内部的金矿数为奇数。
分析: 直接暴力枚举的时间复杂度是o(n^4),可以先进行预处理
定义数组dp[i][j] 表示在房子 i 和放在 j 之间连线的上方的金矿数量,
则 房子 i,j, k, 内部的金矿数为 sum = dp[i][j]-dp[i][k]-dp[j][k]
#include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #define clr(x)memset(x,0,sizeof(x)) struct node { __int64 x,y; }h[105],g[1005]; int cmp(const void*p1,const void*p2) { node *c=(node*)p1; node *d=(node*)p2; return c->x-d->x; } int dp[105][105]; __int64 mul(node a,node b,node c) { return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); } int main() { int n,m,i,j,k,res,tot,ca=1; while(scanf("%d%d",&n,&m)!=EOF) { for(i=0;i<n;i++) scanf("%I64d%I64d",&h[i].x,&h[i].y); for(i=0;i<m;i++) scanf("%I64d%I64d",&g[i].x,&g[i].y); qsort(h,n,sizeof(h[0]),cmp); qsort(g,n,sizeof(g[0]),cmp); clr(dp); for(i=0;i<n;i++) for(j=i+1;j<n;j++) { tot=0; for(k=0;k<m;k++) if(g[k].x>=h[i].x&&g[k].x<=h[j].x&&mul(h[i],g[k],h[j])<0) tot++; dp[i][j]=tot; } res=0; for(i=0;i<n;i++) for(j=i+1;j<n;j++) for(k=j+1;k<n;k++) { tot=dp[i][j]-dp[i][k]-dp[j][k]; if(tot&1) res++; } printf("Case %d: %d\n",ca++,res); } return 0; }