TOPIC

PROBLEM 1464 - URI Fórum 1.0

beecrowd asked on Aug 30 2013

URI Online Judge Fórum 1.0

MOD

This topic was solved and cannot recieve new replies.

  • ldcampos replied 9 years ago

    Pesquise Convex Hull, eu usei o algoritmo de Graham Scan. A ideia do problema é contar quantas vezes vc consegue achar um polígono que possa cercar os pontos, depois vc elimina os pontos que pertence ao perímetro do polígono, e continua fazendo isso até ter menos que 3 pontos.A resposta depende da paridade do número de camadas. Tome cuidado com pontos duplicados e retire não só os pontos do Convex Hull mas tbm os que estiverem no perímetro do polígono. Boa sorte!

  • erribeiro replied 8 years ago

    import java.awt.Point; import java.util.LinkedList; import java.util.Scanner;

    public class CamadasDeCebola{ public static void main(String args[]){ Scanner scanner = new Scanner(System.in);

        int n =  scanner.nextInt();
        while(n != 0){
            LinkedList<Point> pontos = new LinkedList<Point>();         
            for(int i=0;i<n;i++){
                pontos.add(new Point(scanner.nextInt(), scanner.nextInt()));
            }
    
            QuickHull quickHull = new QuickHull(pontos);
            if(quickHull.execute()%2 == 0 ){
                System.out.println("Do not take this onion to the lab!");
            }else{
                System.out.println("Take this onion to the lab!");
            }
            n =  scanner.nextInt();
        }                                              
    }

    }
    class QuickHull { private LinkedList entrada; private LinkedList result; private int cascas; public QuickHull(LinkedList points){ this.entrada = points; this.result = new LinkedList<>(); cascas = 0; }

    private int[] furtherLeftAndFurtherRight(LinkedList<Point> points){
        int minPoint = -1, maxPoint = -1;
        int minX = Integer.MAX_VALUE;
        int maxX = Integer.MIN_VALUE;
        for (int i = 0; i < points.size(); i++){
            if (points.get(i).x < minX){
                minX = points.get(i).x;
                minPoint = i;
            }
            if (points.get(i).x > maxX){
                maxX = points.get(i).x;
                maxPoint = i;
            }
        }
    
        int[] resultado = {minPoint, maxPoint}; 
        return resultado;
    }
    public int execute(){               
        if (entrada.size() < 3){
            System.out.println("CASCAS: "+cascas);
            return cascas;
        }
    
        /**
         * No eixo x, pega o ponto mais esquerda e direita.     
         */
        int[] resultado = furtherLeftAndFurtherRight(entrada);
        int minPoint = resultado[0];
        int maxPoint = resultado[1];
    
        Point A = entrada.get(minPoint);
        Point B = entrada.get(maxPoint);
    
        /**
         * Adiciona os dois pontos extremos ao Convex Hull.
         */
        result.add(A); 
        result.add(B);
        /**
         * Remove os dois pontos extremos do conjunto de pontos de entrada. 
         */
        entrada.remove(A);
        entrada.remove(B);
    
        /**
         * Criar dois subconjuntos, um a direita da reta e outra a esquerda.
         */
        LinkedList<Point> leftSet  = new LinkedList<Point>();
        LinkedList<Point> rightSet = new LinkedList<Point>();
    
        for (int i = 0; i < entrada.size(); i++){
            Point p = entrada.get(i);
            if (pointLocation(A, B, p) == -1)
                leftSet.add(p);
            else if (pointLocation(A, B, p) == 1)
                rightSet.add(p);
        }
    
        hullSet(A, B, rightSet);
        hullSet(B, A, leftSet);
    
        this.cascas++;        
        if(entrada.size() > 2){   
            for (Point point : entrada) {
                System.out.println(point);
            }
            System.out.println("");
            System.out.println();
            execute();
        }
        //System.out.println("Cascas: "+cascas);
    
        return cascas;
    }
    
    public void hullSet(Point A, Point B, LinkedList<Point> set){
        int insertPosition = result.indexOf(B);
    
        if (set.size() == 0)
            return;
        if (set.size() == 1){
            Point p = set.get(0);
            set.remove(p);
            result.add(insertPosition, p);         
            entrada.remove(p); // ->            
            return;
        }
        Double furtherDistance = Double.MIN_VALUE;
        int furthestPoint = -1;
        for (int i = 0; i < set.size(); i++){
            Point p = set.get(i);
            //int distance = distance(A, B, p);
            double distance = pointToLineDistance(A, B, p);
            if (distance > furtherDistance){
                furtherDistance = distance;
                furthestPoint = i;
            }
        }
    
        Point P = set.get(furthestPoint);
        set.remove(furthestPoint);        
    
        this.result.add(insertPosition, P);
        entrada.remove(P); // ->
    
        /**
         * Determina quais pontos estão a esquerda de AP
         */
    
        LinkedList<Point> leftSetAP = new LinkedList<Point>();
        for (int i = 0; i < set.size(); i++){
            Point M = set.get(i);
            if (pointLocation(A, P, M) == 1){
                leftSetAP.add(M);
            }
        }
    
        /**
         * Determina quais pontos estão a esquerda de PB
         */
    
        LinkedList<Point> leftSetPB = new LinkedList<Point>();
        for (int i = 0; i < set.size(); i++)
        {
            Point M = set.get(i);
            if (pointLocation(P, B, M) == 1)
            {
                leftSetPB.add(M);
            }
        }
        hullSet(A, P, leftSetAP);
        hullSet(P, B, leftSetPB);            
    
    }    
    
    public double pointToLineDistance(Point A, Point B, Point P){
        double normalLength = Math.sqrt((B.x-A.x)*(B.x-A.x)+(B.y-A.y)*(B.y-A.y));
        return Math.abs((P.x-A.x)*(B.y-A.y)-(P.y-A.y)*(B.x-A.x))/normalLength;
    }
    
    public int pointLocation(Point A, Point B, Point P){
        int cp1 = (B.x - A.x) * (P.y - A.y) - (B.y - A.y) * (P.x - A.x);        
        if (cp1 > 0) 
            return 1;
        else if (cp1 == 0) 
            return 0;
        else 
            return -1;       
    }

    } Olá, estou recebendo "Wrong answer" entranto não estou conseguindo encontrar o erro, estou utilizando a versão quickHull para resolver a questão e me deparei com a seguinte entrada: 5 1 1 2 2 3 3 4 4 5 5

    Take this onion to the lab! Testei essa entrada no toolkit é esse foi o resultado, contudo esses pontos fazem parte da mesma reta, e pelo que sei eles não deveriam formar um convex Hull, estou com essa dúvida também

  • lblanger replied 9 years ago

    Eu também estou com Wrong Answer 20%. O enunciado não explica muito claramente como tratar pontos colineares em cada camada. Já tentei considerá-los e depois ignorá-los, mas continuo com o mesmo resultado.

  • mbustamante0 replied 9 years ago

    Galera alguem pode me ajudar a encontrar o erro?? to levando 20%wa

    #include <iostream>
    #include <stack>
    #include <cmath>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    using namespace std;
    
    typedef struct{
        int x, y;
    }Ponto;
    Ponto p0;
    
    Ponto nextToTop(stack<Ponto> pilha){
        Ponto x = pilha.top();
        pilha.pop();
        Ponto ret = pilha.top();
        pilha.push(x);
        return ret;
    }
    
    int cross(const Ponto & p, const Ponto & p1, const Ponto & p2){
        return (p2.x - p1.x)*(p1.y - p.y) - (p2.y - p1.y)*(p1.x - p.x);
    }
    
    int dist(const Ponto & p1, const Ponto & p2){
        return sqrt(pow(p2.x - p1.x,2)+pow(p2.y - p1.y,2));
    }
    
    int comparacao(const void * a, const void * b){
        Ponto *p1 = (Ponto *)a;
        Ponto *p2 = (Ponto *)b;
        int value = cross(p0, *p1, *p2);
        if(value == 0)
            return dist(p0, *p1) > dist(p0, *p2)?1:-1;
        return value > 0? 1:-1;
    
    }
    
    int convexHull(Ponto pontos[], int n){
        int cont = 0;
        while(n > 3){
            int index = 0;
            for(int i = 1; i < n; ++i){
                if(pontos[i].y < pontos[index].y)
                    index = i;
                else if(pontos[i].y == pontos[index].y && pontos[i].x < pontos[index].x)
                    index = i;
            }
    
            p0 = pontos[index];
            pontos[index] = pontos[0];
            pontos[0] = p0;
    
            Ponto naoSelecionados[n];
    
            Ponto tiraRepitidos[n];
            qsort(&pontos[1], n-1, sizeof(Ponto), comparacao);
    
            tiraRepitidos[0] = pontos[0];
            int k =0;
            for (int i = 1; i < n; ++i){
                if(pontos[i].x != tiraRepitidos[k].x || pontos[i].y != tiraRepitidos[k].y)
                    tiraRepitidos[++k] = pontos[i];
            }
            n = k+1;
            memcpy(pontos, tiraRepitidos, sizeof(Ponto)*n);
    
            stack<Ponto>pilha;
            pilha.push(pontos[0]);
            pilha.push(pontos[1]);
            pilha.push(pontos[2]);
    
            for(int i = 3, j = 0; i < n; ++i){
                while(cross(nextToTop(pilha), pilha.top(), pontos[i]) > 0){
                    naoSelecionados[j++] = pilha.top();
                    pilha.pop();
                }
                pilha.push(pontos[i]);
            }
    
            while(!pilha.empty()){
                --n;
                pilha.pop();
            }
            ++cont;
            memcpy(pontos, naoSelecionados, sizeof(Ponto)*n);
        }
        if(n == 3)
            ++cont;
    
        return cont;
    }
    
    int main(){
        Ponto pontos[3000], x;
        int n;
        while(scanf("%d", &n) && n > 0){
            for(int i = 0; i < n; ++i){
                scanf("%d %d",&pontos[i].x, &pontos[i].y);
            }
    
            int lears = convexHull(pontos, n);
            if(lears%2 == 0)
                cout << "Do not take this onion to the lab!\n";
            else
                cout << "Take this onion to the lab!\n";
        }
        return 0;
    }
  • wsuzukayama replied 9 years ago

    Alguma dica ?