본문 바로가기

Dot Algo∙ DS/PS

[BOJ] 백준 7869번 두 원 (Java)

    #7869 두 원

    난이도 : 골드 3

    유형 : 기하학

     

    7869번: 두 원

    첫째 줄에 두 원의 중심과 반지름 x1, y1, r1, x2, y2, r2가 주어진다. 실수는 최대 소수점 둘째자리까지 주어진다.

    www.acmicpc.net

    ▸ 문제

    두 원이 주어졌을 때, 교차하는 영역의 넓이를 소수점 셋째자리까지 구하는 프로그램을 작성하시오.

     입력

    첫째 줄에 두 원의 중심과 반지름 x1, y1, r1, x2, y2, r2가 주어진다. 실수는 최대 소수점 둘째자리까지 주어진다.

     출력

    첫째 줄에 교차하는 영역의 넓이를 반올림해 소수점 셋째자리까지 출력한다.

     

    문제 풀이  

    두 원이 중심으로부터 두 접점으로 까지의 부채꼴 합한 면적 - 두 삼각형 면적을 뺴면 두 원의 교차면적을 구할 수 있다. 해당 을 참고하면 공식이 자세히 나와있다. 

     

    https://mathworld.wolfram.com/Circle-CircleIntersection.html

     

    각 R의 부채꼴 내각을 Θ라고 하면 각 부채꼴을 합한 면적은  r^2*Θ / 2이다. 각 삼각형의 면적은  r^2/sin(Θ)이다. 그럼 두 원의 교차면적은 A = (\(r1^2\)(\(Θ1 - sin(Θ1)\)) + \(r2^2\)(\(Θ2 - sin(Θ2)\))/2로 구할 수 있다. 그래서 Θ를 구해보면 제 2 코사인 법칙으로 다음과 같이 구할 수 있다.

     

    Math.acos((r1 * r1 + dis * dis- r2 * r2) / (2 * r1 * dis));

     

    풀이 코드 

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.StringTokenizer;
    
    public class Main {
    
    	public static void main(String[] args) throws  IOException{
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    		StringTokenizer st = new StringTokenizer(br.readLine());
    		
    		double x1 = Double.parseDouble(st.nextToken());
    		double y1 = Double.parseDouble(st.nextToken());
    		double r1 = Double.parseDouble(st.nextToken());
    		double x2 = Double.parseDouble(st.nextToken());
    		double y2 = Double.parseDouble(st.nextToken());
    		double r2 = Double.parseDouble(st.nextToken());
    		
    		double dis = getDis(x1, y1, x2, y2);
    		double result = 0; // 원의 접점이 없는 경우 
    		if(Math.abs(r1 - r2) >= dis) { // 한 원이 내부에 있는 경우 
    			result = Math.PI * Math.pow(Math.min(r1, r2), 2);
    		} else if(r1+r2 > dis) { // 두 원의 접점이 2개인 경우 
    			double theta1 = Math.acos((r1 * r1 + dis * dis- r2 * r2) / (2 * r1 * dis));
    			double theta2 = Math.acos((r2 * r2 + dis* dis- r1 * r1) / (2 * r2 * dis));
    
    			double w1 = (r1 * r1 * theta1) - (r1 * r1 * Math.sin(2 * theta1) / 2);
    			double w2 = (r2 * r2 * theta2) - (r2 * r2 * Math.sin(2 * theta2) / 2);
    			result = w1+w2;
    		}
    		System.out.println(String.format("%.3f", result));
    	}
    	static double getDis(double x1, double y1, double x2, double y2) {
    		return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
    	}
    }