Parallel Lines(找最多平行线)

原题: https://cn.vjudge.net/problem/UVALive-8367

题意:

给出多个点(最多12个),问最多有多少对平行线(每个点只能用一次)

解析:

12个点暴力dfs会TLE,所以需要先筛掉一些选择

对与一条边,对答案可能有贡献,当且仅当有一条其他边和这条边平行

筛完后即可直接dfs,以为一个点不可能有很多有效边

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
typedef pair<int,int> pill;
int x[17],y[17];

struct Vector{
    int x,y;
    Vector(int x,int y):x(x),y(y){}
    bool operator < (const Vector &a)const{
        return x<a.x;
    }

};

bool inLine(Vector a,Vector b){
    return a.x*b.y-b.x*a.y==0;
}

bool link[20][20];
int n;

struct node{
    int l[17];
};

void out(node a){
    for(int i=1;i<=n;i++)printf("%d ",a.l[i]);printf("\n");
}

int getVal(node a){
    //out(a);
    multiset<Vector>S;
    for(int i=1;i<=n;i++){
        if(a.l[i]!=0&&a.l[i]<i){Vector tmp(x[i]-x[a.l[i]],y[i]-y[a.l[i]]);S.insert(tmp);}
    }
    int ans=0;
    for(multiset<Vector>::iterator it=S.begin();it!=S.end();it++){
        int now=1;
        multiset<Vector>::iterator it2=it;it2++;
        for(;it2!=S.end();)
            if(inLine(*it,*it2))now++,S.erase(it2++);
            else it2++;
        ans+=now*(now-1)/2;
    }
    return ans;
}

int dfs(int pos,node sta){
    if(pos==n+1)return getVal(sta);
    if(sta.l[pos])return dfs(pos+1,sta);
    int ans=0;
    for(int i=pos+1;i<=n;i++){
        if(link[pos][i]&&!sta.l[i]){
            sta.l[pos]=sta.l[i]=pos;
            ans=max(ans,dfs(pos+1,sta));
            sta.l[pos]=sta.l[i]=0;
        }
    }
    ans=max(ans,dfs(pos+1,sta));
    return ans;
}

int main(){
    while(cin>>n){
        memset(link,0,sizeof(link));
        for(int i=1;i<=n;i++){
            scanf("%d%d",&x[i],&y[i]);
        }
        for(int i=1;i<n;i++){
            for(int j=i+1;j<=n;j++){
                Vector a(x[i]-x[j],y[i]-y[j]);
                for(int k=i;k<n;k++){
                    if(k==i)
                    for(int q=j+1;q<=n;q++){
                        Vector b(x[k]-x[q],y[k]-y[q]);
                        if(inLine(a,b))
                            link[i][j]=link[k][q]=1
                            ;//,printf(" link (%d %d)(%d %d)\n",i,j,k,q);
                    }
                    else
                    for(int q=k+1;q<=n;q++){
                        Vector b(x[k]-x[q],y[k]-y[q]);
                        if(inLine(a,b))
                            link[i][j]=link[k][q]=1
                            ;//,printf(" link (%d %d)(%d %d)\n",i,j,k,q);
                    }
                }
            }
        }
        node tmp;memset(tmp.l,0,sizeof(tmp.l));
        int ans=dfs(1,tmp);
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/84202760