zoukankan      html  css  js  c++  java
  • POJ

    传送门:Space Ant

    题意

    给出n个点,有一个小人,他每次只能往左边拐,并且不能走以前走过的路,走的路线也不能相交,问他怎么走可以走的路程最大。

    题解

    可以想到肯定是所有的点都走到路径会最大,然后就很容易想到这不就可以一直凸包了吗!!每次形成凸包的点删掉再继续凸包,然后每次把点的编号加入队列中,直到没有点没被走过。我用的是graham算法的凸包,先找到纵坐标最小的点,第一次按照极角排序是判断和该点连线的极角,后边都是和前一次凸包里的最后一个点的连线形成的极角判断。(想法很简单,实现好麻烦....)

    代码

     1 #include<stdio.h>
     2 #include<algorithm>
     3 #include<string.h>
     4 #include<queue>
     5 #include<math.h>
     6 #include<iostream>
     7 #define ll long long
     8 using namespace std;
     9 
    10 const ll maxn=1e3+10;
    11 
    12 struct node
    13 {
    14     ll x,y;
    15     ll id;
    16 }p[maxn],s[maxn],q[maxn];
    17 
    18 ll xx,yy;
    19 
    20 ll cross(node a,node b,node c)
    21 {
    22     return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
    23 }
    24 
    25 ll cmp1(node a,node b)
    26 {
    27     if(a.y==b.y) return a.x<b.x;
    28     return a.y<b.y;
    29 }
    30 
    31 ll cmp2(node a,node b)
    32 {
    33     if(atan2(a.y-yy,a.x-xx)-atan2(b.y-yy,b.x-xx)==0) return a.x<b.x;
    34     else return atan2(a.y-yy,a.x-xx)<atan2(b.y-yy,b.x-xx);
    35 }
    36 
    37 queue<ll>qq;
    38 bool vis[maxn];
    39 
    40 int main()
    41 {
    42     ios::sync_with_stdio(false);
    43     cin.tie(0);
    44     cout.tie(0);
    45     int t;
    46     cin>>t;
    47     while(t--){
    48         memset(vis,0,sizeof(vis));
    49         while(!qq.empty()) qq.pop();
    50         ll n;
    51         cin>>n;
    52         for(ll i=0;i<n;i++){
    53             cin>>q[i].id>>q[i].x>>q[i].y;
    54             p[i]=q[i];
    55         }
    56         sort(q,q+n,cmp1);
    57         ll id;
    58         xx=q[0].x,yy=q[0].y,id=q[0].id;
    59         qq.push(q[0].id);
    60         vis[q[0].id]=1;
    61         while(1){
    62             ll l=0;
    63             for(ll i=0;i<n;i++) if(!vis[q[i].id]) p[l++]=q[i];
    64 //            cout<<l<<endl;
    65             if(!l) break;
    66             sort(p,p+l,cmp2);
    67             if(l==1) {qq.push(p[0].id);break;}
    68             else if(l==2) {qq.push(p[0].id),qq.push(p[1].id);break;}
    69             else{
    70                 s[0].x=xx,s[0].y=yy,s[0].id=id;s[1]=p[0];
    71                 ll top=1;
    72                 for(ll i=1;i<l;i++){
    73                     while(top&&cross(s[top-1],s[top],p[i])<=0) top--;    //<=可以去掉重边
    74                     //如果是向右转,这个中间点就不是我们要找的点
    75                     s[++top]=p[i];//如果是向左转,就加进来
    76                 }
    77                 for(ll i=0;i<=top;i++){
    78                     if(!vis[s[i].id]) qq.push(s[i].id);
    79                     vis[s[i].id]=1;
    80                 }
    81                 xx=s[top].x,yy=s[top].y,id=s[top].id;
    82             }
    83         }
    84         cout<<qq.size();
    85         while(!qq.empty()) {
    86             cout<<' '<<qq.front();
    87             qq.pop();
    88         }
    89         cout<<endl;
    90     }
    91     return 0;
    92 }
  • 相关阅读:
    liunx基本命令
    liunx—awk
    python—__name__
    python—url路径拼接/编码
    python—__init__作用
    单元测试
    2、选择排序
    1、算法简介
    在命令行输入python出现“Warning:This Python interpreter is in a conda environment, but the environment has not been activated. Libraries may fail to load. To activate this environment please see https://conda.
    如何明确区分代码中的1和l
  • 原文地址:https://www.cnblogs.com/lilibuxiangtle/p/13745017.html
Copyright © 2011-2022 走看看