zoj 1030 (dfs+几何)

本文介绍了一种从每个点开始,通过深度优先搜索(DFS)算法在几何圈内寻找并判断是否存在其他点的方法。该算法的时间复杂度为O(n^3),详细解释了如何实现几何圈的搜索和去重过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//从每一个点开始,向某一个几何方向dfs搜索几何圈,然后判断几何圈里有没有其他的点,再把几何圈去重就是答案,O(n^3).

#include<stdio.h>
#include<math.h>
#include<vector>
#include<set>
#include<string.h>
#include<algorithm>

using namespace std;

struct Point{
    int x,y;
    Point(int a=0,int b=0):x(a),y(b){}
};

Point operator-(Point a,Point b){ return Point(a.x-b.x,a.y-b.y); }
Point operator+(Point a,Point b){ return Point(a.x+b.x,a.y+b.y); }
int operator*(Point a,Point b){ return a.x*b.x+a.y*b.y; }
int operator==(Point a,Point b){ return a.x==b.x&&a.y==b.y; }
double Len(Point a){  return sqrt(a.x*a.x+a.y*a.y); }
int cross(Point a,Point b){
    return a.x*b.y-a.y*b.x;
}
double angle(Point a,Point b){
    return acos((a*b)/(Len(a)*Len(b)));
}
int online(Point a,Point b,Point c)
{
    return  (a==c)||(b==c)||(cross(a-c,b-c)==0&&((a-c)*(b-c)<0));
}
int Polygon_contains(Point point,Point *points,int n) {
    int i, j, status=0;
    for (i=0,j=n-1;i<n;j=i++){
        if(online(points[i],points[j],point)) return 0;
        if((((points[i].y<=point.y)&&(point.y<points[j].y))
        ||((points[j].y<=point.y)&&(point.y<points[i].y)))
        &&(point.x <(points[j].x - points[i].x)*(point.y - points[i].y)
        /(points[j].y - points[i].y) + points[i].x))
            status = !status;
    }
    return status;
}

set <int> ans;
int size,vis[220],used[220],pre[220],n,rt;
Point points[210],polygons[210];
vector <int> edge[210];
void dfs(int root,int pa,int dep)
{
    int i,u;
    if(dep-1>size) return;
    if(vis[root]){
        if(root==rt&&dep-vis[root]==size){
            u=pa;i=1;
            memset(used,0,sizeof(used));
            polygons[0]=points[root];used[root]=1;
            while(u!=root){
                used[u]=1;
                polygons[i++]=points[u];u=pre[u];
            }
            for(i=1;i<=n;i++){
                if(!used[i]){
                    if(Polygon_contains(points[i],polygons,size)) return ;
                }
            }
            for(i=1,u=0;i<=n;i++){
                if(used[i]) u=u*1313+i;
            }
            ans.insert(u);
        }
        return ;
    }
    vis[root]=dep;
    int tag=-1;double yy;
    Point U,V=points[pa]-points[root],B;
    for(i=0;i<edge[root].size();i++){
        u=edge[root][i];
        if(u==pa) continue;
        U=points[u]-points[root];
        if(tag==-1){ tag=u;yy=angle(V,U);B=U; }
        else {
            if(cross(U,V)>0&&(cross(B,V)<=0||cross(B,V)>0&&angle(V,U)<yy)
            ||cross(U,V)<=0&&cross(B,V)<=0&&(angle(V,U)>yy)){
                tag=u;B=U;
                yy=angle(V,U);
            }
        }
    }
    if(tag!=-1){
        if(!vis[tag]) pre[tag]=root;
        dfs(tag,root,dep+1);
    }
}

int main()
{
    int i,j,m,cas,k,t;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d",&n);
        for(i=0;i<=n;i++)edge[i].clear();
        for(i=1;i<=n;i++){
            scanf("%d",&k);
            scanf("%d%d",&points[k].x,&points[k].y);
            scanf("%d",&m);
            for(j=0;j<m;j++){
                scanf("%d",&t);
                edge[k].push_back(t);
            }
        }
        ans.clear();
        scanf("%d",&size);
        for(i=1;i<=n;i++){
            rt=i;
            for(j=0;j<edge[i].size();j++){
                memset(vis,0,sizeof(vis));vis[i]=1;
                pre[edge[i][j]]=i;
                dfs(edge[i][j],i,2);
            }
        }
        printf("%d\n",ans.size());
    }
    return 0;
}

/*
8
0 0
5 0
5 1
3 1
3 3
5 3
5 5
0 5
100
*/




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值