tookunn’s diary

主に競技プログラミング関係

Codeforces #352 Div2 C

問題文

codeforces.com

考察

distance(x_i,y_i,tx,ty)]をi番目のbottleから(tx,ty)までの距離とする。
sum(distance(x,y,tx,ty)) = \sum_{i=0}^{N} distance(x_i,y_i,tx,ty)

・よく考えるとabそれぞれ最初に拾うbottleと最後に拾うbottle以外は(tx,ty)(x_i,y_i)を往復するので2 * distance(x_i,y_i,tx,ty)となる。

・あとはaから最初に到達する最短のbottleを選んで,bから最初に到達する残りbottleを探索,bから最初に到達する最短のbottleを選んで,aから最初に到達する残りのbottleを探索して総距離の最小値を求める。

aまたはbがすべてのbottleを拾う場合の最小値も求める必要がある。

ソースコード

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.NoSuchElementException;

import java.util.*;

public class Main {
	
	int ax,ay,bx,by,tx,ty,N;
	int[] x,y;
	double[] td;
	double[] ad,bd;
	
	public double dis(int x,int y,int a,int b){
		return Math.sqrt((long)(x - a) * (x - a) + (long)(y - b) * (y - b));
	}
	
	public void solve() {
		ax = nextInt();
		ay = nextInt();
		bx = nextInt();
		by = nextInt();
		tx = nextInt();
		ty = nextInt();
		N = nextInt();
		
		x = new int[N];
		y = new int[N];
		td = new double[N];
		ad = new double[N];
		bd = new double[N];
		
		double sum = 0.0;
		for(int i = 0;i < N;i++){
			int x = nextInt();
			int y = nextInt();
			
			td[i] = dis(x,y,tx,ty);
			sum += td[i];
			
			ad[i] = dis(x,y,ax,ay);
			bd[i] = dis(x,y,bx,by);
		}
		sum *= 2;
		
		double ans = Double.MAX_VALUE;
		
		//priority A
		int a = 0;
		for(int i = 0;i < N;i++){
			if(ad[a] - td[a] > ad[i] - td[i]){
				a = i;
			}
		}
		
		for(int i = 0;i < N;i++){
			if(a == i)continue;
			ans = Math.min(ans,sum + ad[a] - td[a] + bd[i] - td[i]);
		}
		//not use B
		ans = Math.min(ans,sum - td[a] + ad[a]);
		for(int i = 0;i < N;i++){
			if(i == a)continue;
			ans = Math.min(ans,sum - td[a] + ad[a]);
		}
		
		//priority B
		int b = 0;
		for(int i = 0;i < N;i++){
			if(bd[b] - td[b] > bd[i] - td[i]){
				b = i;
			}
		}
		
		for(int i = 0;i < N;i++){
			if(b == i)continue;
			ans = Math.min(ans,sum + bd[b] - td[b] + ad[i] - td[i]);
		}
		
		//not use A
		ans = Math.min(ans,sum - td[b] + bd[b]);
		for(int i = 0;i < N;i++){
			if(i == b)continue;
			ans = Math.min(ans,sum - td[b] + bd[b]);
		}
		out.println(String.format("%.09f",ans));
		
	} 

	public static void main(String[] args) {
		out.flush();
		new Main().solve();
		out.close();
	}
	
	/* Input */
	private static final InputStream in = System.in;
	private static final PrintWriter out = new PrintWriter(System.out);
	private final byte[] buffer = new byte[2048];
	private int p = 0;
	private int buflen = 0;

	private boolean hasNextByte() {
		if (p < buflen)
			return true;
		p = 0;
		try {
			buflen = in.read(buffer);
		} catch (IOException e) {
			e.printStackTrace();
		}
		if (buflen <= 0)
			return false;
		return true;
	}

	public boolean hasNext() {
		while (hasNextByte() && !isPrint(buffer[p])) {
			p++;
		}
		return hasNextByte();
	}

	private boolean isPrint(int ch) {
		if (ch >= '!' && ch <= '~')
			return true;
		return false;
	}

	private int nextByte() {
		if (!hasNextByte())
			return -1;
		return buffer[p++];
	}

	public String next() {
		if (!hasNext())
			throw new NoSuchElementException();
		StringBuilder sb = new StringBuilder();
		int b = -1;
		while (isPrint((b = nextByte()))) {
			sb.appendCodePoint(b);
		}
		return sb.toString();
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}
}