c – 关于IntersectingConvexHull的一个topcoder难题
我四小时前第一次问这个问题.事实上,我已经搜索了这个问题超过6个小时,但仍然无法理解.
这个问题是通过给你x [n]和y [n]给你n分.您应该找到这些点的两个子集,其凸包相交.您的回答应该是满足上述规则的案件数量.
有许多我无法理解的解决方案,以下是其中之一.例如,什么是ccw?结果由两部分组成,为什么? 以下是一个解决此问题的示例代码: #include <vector> #include <iostream> using namespace std; const long long mod=1000000007ll; struct IntersectingConvexHull{ public: int count(vector<int> x,vector<int> y){ int n = x.size(); long long P2[110]; P2[0]=1ll; for(int i=1;i<=n;i++){ P2[i]=P2[i-1]*2%mod; } long long C[110][110]; for(int i=0;i<=n;i++){ C[i][0]=C[i][i]=1ll; for(int j=1;j<i;j++){ C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; } } long long X[100],Y[100]; for(int i=0;i<=n;i++){ X[i]=x[i]; Y[i]=y[i]; } long long ans=0; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(i==j)continue; int c1=0,c2=0; for(int k=0;k<n;k++){ if(k==i||k==j){ continue; } long long ccw=(X[i]-X[k])*(Y[j]-Y[k])-(Y[i]-Y[k])*(X[j]-X[k]); if(ccw<0){ c1++; } else{ c2++; } } if(c1>=2&&c2>=2){ ans+=((P2[c1]+mod-c1-1)%mod)*((P2[c2]+mod-c2-1)%mod)%mod; ans%=mod; } } } long long A=0ll; for(int i=3;i<=n;i++){ for(int j=3;j<=n-i;j++){ A+=C[n][i]*C[n-i][j]%mod; A%=mod; } } return (A+mod-ans)%mod; } }; 解决方法
两个集合必须至少有三个点,以使船体的交叉点具有非零区域.该代码计算满足此标准的分区数减去交叉区域为零的分区数. (P2是2的幂.C是二项式系数.)
当且仅当存在将两个船体分开的线(Hyperplane separation theorem)时,两个凸包的交叉点具有零面积.我认为我们需要扩展这个结果,实际上,(在正确的假设下)有两条线将船体分开并触及两者. 最后一个循环计算minuend.计算减数的前一个是几何考虑因素.代码在所有点对上循环,并且考虑到它们的直线,通过有符号区域测试计算每一侧的点数.它增加了从每一侧选择两个或多个点的方法的数量,从而确保,如果我们在一个船体中包括该对中的第一个点而在另一个船体中包括该对中的第二个点,我们得到两个船体由线支持并由线分隔. 我不知道这个代码如何处理退化输入(两个重复点,三个共线点). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |