poj 1619 题解

题意:有n个点,求一条有向路径(从某点到y轴的投影出发)满足:

①在路径上的点数最多

②路径只能直走或左转

③路径不自交

 

M组数据(1 <= M <= 10),1 <= N <= 50

 

题解:假设已经到达某个点,则以该点为极坐标原点,极角最小且距离最近的合法点就是下一个该走的点(由限制②和③可以看出,这样的点下一步可以走到的范围包含了其他合法点可以走到的范围)

实现时枚举出发点,判断极角使用点积;判断合法则使用叉积,并且存储一个数组,记录之前的点,判断线段相交(使用规范相交即可)与是否走到重复点。

 

Debug半天发现自己求极角cos值公式写错了(输出中间变量的时候就在想,怎么这些cos值绝对值这么小),忍不住笑出了声。

代码乱糟糟的

 

 

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

#define rep(i,a,b) for (int i=a;i<=b;++i)

const double eps=1e-7;

struct point{
    int x,y;
    point(){}
    point (int a,int b): x(a),y(b) {}

    friend point operator + (const point &a,const point &b){
        return point(a.x+b.x,a.y+b.y);
    }

    friend point operator - (const point &a,const point &b){
        return point(a.x-b.x,a.y-b.y);
    }

    friend point operator * (const int &r,const point &a){
        return point(r*a.x,r*a.y);
    }

    friend bool operator == (const point &a,const point &b){
        return (abs(a.x-b.x)<eps && abs(a.y-b.y)<eps);
    }

    double norm(){
        return sqrt(double(x*x+y*y));
    }

};

inline int det(point a,point b) {return a.x*b.y-a.y*b.x;}
inline int dot(point a,point b) {return a.x*b.x+a.y*b.y;}
inline int dist(point a,point b) {return (a-b).norm();}

inline bool seg_cross_seg(point a,point b,point c,point d)
{
    if (min(c.x,d.x)>max(a.x,b.x) || min(a.x,b.x)>max(c.x,d.x) || min(c.y,d.y)>max(a.y,b.y) || min(a.y,b.y)>max(c.y,d.y))
        return false;
    return det(a-c,d-c)*det(b-c,d-c)<0 && det(c-a,b-a)*det(d-a,b-a)<0;
}

inline int sqr(int x){return x*x;}

point s[60];
int tot,ans[60],pre[60];
int n,t,x,y,T;

bool ok(int now,int nxt,point b)
{

    if (now==nxt || s[nxt]==b) return false;
    if (det(s[now]-b,s[nxt]-s[now])<0) return false;
    int j=now;
    while (pre[j]!=-1)
    {
        if ((j==nxt) || seg_cross_seg(s[now],s[nxt],s[pre[j]],s[j])) return false;
        j=pre[j];
    }
    if (j==nxt ||seg_cross_seg(s[now],s[nxt],point(0,s[j].y),s[j])) return false;
    return true;
}

void dfs(point b,int now,int dep)
{
    bool flag=false;
    double temp1=-100,temp2;
    int nex=-1;
    rep(i,1,n) if (ok(now,i,b))
    {
        flag=true;
        temp2=dot(s[now]-b,s[i]-s[now])/(s[now]-b).norm()/(s[i]-s[now]).norm();
        if (temp2>temp1+eps || (abs(temp2-temp1)<eps && dist(s[i],s[now])<dist(s[now],s[nex])))
        {
            temp1=temp2;
            nex=i;
        }
    }
    if (flag)
    {
        pre[nex]=now;
        dfs(s[now],nex,dep+1);
    }   else
    if (dep>tot)
    {
        tot=dep;
        int i=now,j=tot;
        while (i!=-1)
        {
            ans[j]=i;i=pre[i];--j;
        }
    }
}

int main()
{
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&n);
        tot=0;
        rep(i,1,n)
            scanf("%d%d%d",&t,&x,&y),s[t]=point(x,y);
        rep(i,1,n)
        {
            pre[i]=-1;
            dfs(point(0,s[i].y),i,1);
        }
        printf("%d",tot);
        rep(i,1,tot) printf(" %d",ans[i]);
        printf("\n",t);
    }
    return 0;
}

 

posted on 2017-06-20 17:32  心里只有学习  阅读(135)  评论(0编辑  收藏  举报

导航