繁体   English   中英

关于IntersectingConvexHull的一个topcoder难题

[英]One topcoder puzzle about IntersectingConvexHull

我四小时前第一次问这个问题。 事实上,我已经搜索了这个问题超过6个小时,但仍然无法理解。

这个问题是通过给你x [n]和y [n]给你n分。 您应该找到这些点的两个子集,其凸包相交。 您的回答应该是满足上述规则的案件数量。

你在飞机上得到一组有限的点数。 对于每个有效的i,其中一个点具有坐标(x [i],y [i])。 这些点都是截然不同的,没有三个是共线的。

下面,CH(s)表示集合s的凸包:即包含集合s的所有凸多边形中的最小值。 如果满足以下条件,我们说有序对(s1,s2)很有意思:

1.s1是S的子集

2.s2是S的子集

集合s1和s2是不相交的(即,它们没有共同的元素)

4.凸壳CH(s1)和CH(s2)的交点具有正区域注意,来自S的一些点可能保持未使用(即,它们既不在s1中,也不在s2中)。 您将获得所有点的坐标:sx和y。 请计算并返回有趣的对集的数量,模10 ^ 9 + 7。

例子

{1,0,-1,-1,0,1} {1,2,1,-1,-2,-1}

回报:14

我们有14个解决方案:

s1 = {0,1,3},s2 = {2,4,5} s1 = {0,2,3},s2 = {1,4,5} s1 = {0,1,4},s2 = {2,3,5} s1 = {0,2,4},s2 = {1,3,5} s1 = {1,2,4},s2 = {0,3,5} s1 = {0, 3,4},s2 = {1,2,5} s1 = {1,3,4},s2 = {0,2,5} s1 = {0,2,5},s2 = {1,3, 4} s1 = {1,2,5},s2 = {0,3,4} s1 = {0,3,5},s2 = {1,2,4} s1 = {1,3,5}, s2 = {0,2,4} s1 = {2,3,5},s2 = {0,1,4} s1 = {1,4,5},s2 = {0,2,3} s1 = { 2,4,5},s2 = {0,1,3}

有许多我无法理解的解决方案,以下是其中之一。 例如,什么是ccw? 结果由两部分组成,为什么? 你能给我一些算法名称,一些关键词也行,这样我就可以在google上详细搜索了吗?

以下是一个解决此问题的示例代码:

#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是二项式系数。)

当且仅当存在分隔两个船体的线时( 超平面分离定理 ),两个凸包的交点具有零面积。 我认为我们需要扩展这个结果,实际上,(在正确的假设下)有两条线将船体分开并触及两者。

最后一个循环计算minuend。 计算减数的前一个是几何考虑因素。代码在所有点对上循环,并且考虑到它们的直线,通过有符号区域测试计算每一侧的点数。 它增加了从每一侧选择两个或多个点的方法的数量,从而确保,如果我们在一个船体中包括该对中的第一个点而在另一个船体中包括该对中的第二个点,我们得到两个船体由线支持并由线分隔。

我不知道这个代码如何处理退化输入(两个重复点,三个共线点)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM