SW练习_POJ1696_Space Ant_凸包

这个题,神神叨叨,结果却异常无聊。

使用凸包就解决了,但是输入的问题,又对java语言表示了歧视。

具体见代码,BufferedReader StringTokenize scanner都RE,参照最下面的输入类,可以AC

import java.io.*;
import java.util.*;

public class Main{
    static Node1696 baseNode;
    static Node1696[] nodes;
    static boolean[] visited;
    public static void main(String[] args) throws Exception{
        //System.setIn(new FileInputStream("C:\\Users\\XAGDC\\Desktop\\1696.1"));
        //BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
        //StringTokenizer st=new StringTokenizer(reader.readLine());
        //Scanner st=new Scanner(System.in);
        sc.init(System.in);
        int M=sc.nextInt();//测试用例的个数

        for (int i = 0; i <M ; i++) {
            //st=new StringTokenizer(reader.readLine());
            int N=sc.nextInt();//植物的数量
            if(N==1){
                int index=sc.nextInt();
                int x=sc.nextInt();
                int y=sc.nextInt();
                System.out.println("1 "+index);
                continue;
            }
            nodes=new Node1696[N+1];
            visited=new boolean[N+1];
            for (Node1696 node:nodes) {
                node=new Node1696();
            }
            int Min_y=2087654321;
            for (int j = 1; j <=N ; j++) {
                //st=new StringTokenizer(st.readLine());
                int index=sc.nextInt();
                int x=sc.nextInt();
                int y=sc.nextInt();
                if(y<Min_y){
                    Min_y=y;
                }
                nodes[j]=new Node1696(index,x,y);
            }
           nodes[0]=new Node1696(0,0,Min_y);
            baseNode=nodes[0];

            List<Integer> list=new ArrayList<Integer>();
            while(list.size()<N+1){
                //System.out.printf("当前list的size是 %d ,一共有 %d 个数据,数据还没有加完 \n",list.size(),N);


                List<Integer> lt=TUBAO(nodes);
                list.addAll(lt);
                //list.addAll(lt.subList(0,lt.size()-2));


                /*System.out.printf("新的一轮后 N是 %d ,list的size是 %d , (N+1-list.size():%d ) \n list里存放了 ",N,list.size(),(N+1-list.size()));
                for (int j = 0; j <list.size() ; j++) {
                    System.out.printf(list.get(j)+" ");
                }
                System.out.println("");*/
                Node1696 [] nodesNew=new Node1696[N+1-list.size()];
                if(list.size()>=N+1){
                    break;
                }
                nodesNew[0]=baseNode;
                int index=1;

                for(Node1696 node:nodes){
                    if(!visited[node.index] && node.index!=baseNode.index){
                        nodesNew[index]=node;
                        index++;
                    }
                }
                nodes=nodesNew;
            }
            System.out.print(list.size()-1+" ");
            for (int j = 1; j <list.size() ; j++) {//0放的是起点,不需要打印
                System.out.printf(list.get(j)+" ");
            }
            System.out.println("");

        }

        //sc.close();
    }
    public static List<Integer> TUBAO(Node1696[] nodeArr){
        /*System.out.printf("要开始执行TUBAO算法了,先把要处理的节点数据打印一下 \n");
        System.out.printf("base节点信息是 %s  共有节点数 %d \n ",baseNode,nodeArr.length);
        System.out.println(Arrays.toString(nodeArr));*/
        List<Integer> list=new ArrayList<Integer>();
        if(nodeArr.length<=2){
            if(nodeArr.length==1){
                list.add(nodeArr[0].index);
                visited[nodeArr[0].index]=true;
            }else{
                list.add(nodeArr[0].index);
                list.add(nodeArr[1].index);
                visited[nodeArr[0].index]=true;
                visited[nodeArr[1].index]=true;
            }

            return list;
        }

        //baseNode=nodeArr[0];//这是最左下侧的点,是一个极点
        int N= nodeArr.length;
        Arrays.sort(nodeArr,1,N,new Comparator<Node1696>(){//从baseP开始,将点按照夹角排序
            @Override
            public int compare(Node1696 o1, Node1696 o2) {
                return CCW(baseNode,o1,o2) >0 ? -1:1;
            }
        });
        //点在左侧(CCW<0),V++,   点在右侧,需要回溯V--
        int V=1;
        Node1696[] res=new Node1696[N+2];
        res[0]=nodeArr[0];
        res[1]=nodeArr[1];
        visited[nodeArr[0].index]=true;
        visited[nodeArr[1].index]=true;
        /*System.out.printf(" 使用%d 节点为base进行排序 \n",baseNode.index);
        System.out.println("排序之后是 "+Arrays.toString(nodeArr));*/
        for (int i = 2; i <N ; i++) {
            while(CCW(res[V-1] ,res[V] ,nodeArr[i]) <0){
                V--;
            }
            res[++V]=nodeArr[i];
        }
        baseNode=res[V];

        for (int i = 0; i <V ; i++) {
            list.add(res[i].index);
            visited[res[i].index]=true;
        }

        /*System.out.printf("TUBAO执行完了,把找出的点打印一下\n");
        for (Integer i:list
             ) {
            System.out.printf("%d ",i);
        }
        System.out.println("\n");*/
        return list;

    }


    public static int CCW(Node1696 A,Node1696 B,Node1696 C){// >0 逆时针   <0 顺时针
        return A.x*B.y+B.x*C.y+C.x*A.y-(A.y*B.x+B.y*C.x+C.y*A.x) >0?1:-1;
    }

    static class sc{
        static BufferedReader reader;
        static StringTokenizer tokenizer;
        static void init(InputStream input){
            reader=new BufferedReader(new InputStreamReader(input));
            tokenizer=new StringTokenizer("");
        }
        static String next() throws IOException{
            while(!tokenizer.hasMoreTokens()){
                tokenizer=new StringTokenizer(reader.readLine());
            }
            return tokenizer.nextToken();
        }
        static int nextInt() throws IOException{
            return Integer.parseInt(next());
        }

    }
}
class Node1696{
    int index;
    int x;
    int y;

    public Node1696() {
    }

    public Node1696(int index, int x, int y) {
        this.index = index;
        this.x = x;
        this.y = y;
    }

    @Override
    public String toString() {
        return "Node1696{" +
                "index=" + index +
                ", x=" + x +
                ", y=" + y +
                '}'+"\n";
    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值