topcoder srm 465 div1

problem1 link

以两个点$p,q$为中心的两个正方形的边长和最大为$2dist(p,q)$,即$p,q$距离的两倍。

也就是两个$p,q$的连线垂直穿过两个正方形的一对边且平分两个正方形。

problem2 link

简化一下题意就是每个base和每个plant都有一个代价。要么付出某个base的代价,要么付出其对应的plant的代价。

将base和plant建立网络流。

源点到每个plant的边的流量为其代价

base到汇点的边的流量为其代价

base与其对应plant的边的流量为无穷大。

然后求最小割即可。

割到的plant就说明要付出这个plant的代价,割到的base就说明付出这个base的代价。

 

problem3 link

令$p=\frac{1}{d},q=\frac{d-1}{d}$

在$[n-d,n-1]$中任意一个格子,其一步到达$n$的概率都是$p$。恰好经过$t$步到达$n$的概率为$pq^{t-1}$

设$p1[i]$表示先手恰好经过$i$步第一次进入$[n-d,n-1]$区间的概率;

设$p2[i]$表示后手恰好经过$i$步第一次进入$[n-d,n-1]$区间的概率;

设$g(i,j)$表示先手、后手分别经过$i,j$步到达$[n-d,n-1]$区间且先手胜利的概率。

$g(i,j)$的计算方法为:

===============================

g(i,j)=0

if(i<j) { 

$g(i,j) += p1[i]*p2[j]*(1-q^{j-i})$  //在后手未进入最后区间时取得胜利

}

$g(i,j)+=p1[i]*p2[j] * q^{|i-j|} * \frac{d}{d+d-1}$  //都进入最后区间再经过若干轮角逐后取得胜利

===============================

那么答案为所有的$g(i,j)$之和。

 

code for problem1

import java.util.*;
import java.math.*;
import static java.lang.Math.*;

public class TurretPlacement {
	
	public long count(int[] x, int[] y) {
		long result = 0;
		for (int i = 0; i < x.length; ++ i) {
			for (int j = i + 1; j < x.length; ++ j) {
				result += cal(x[i], y[i], x[j], y[j]);
			}
		}
		return result;
	}
	long cal(int x1, int y1, int x2, int y2) {
		long d = (long)(Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) * 2);
		return d * (d - 1) / 2;
	}
}

  

code for problem2

import java.util.*;
import java.math.*;
import static java.lang.Math.*;


class MaxFlow {
	static class node
	{
		int v,cap,next;
	};

	List<node> edges = null;
	int[] head = null;
	int vertexNum;
	int[] pre = null;
	int[] cur = null;
	int[] num = null;
	int[] h = null;

	public MaxFlow(int vertexNum) {
		this.vertexNum = vertexNum;
		edges = new ArrayList<>();
		head = new int[vertexNum];
		Arrays.fill(head, -1);
		pre = new int[vertexNum];
		cur = new int[vertexNum];
		num = new int[vertexNum];
		h = new int[vertexNum];
	}


	private void addEdge(int u, int v, int cap)
	{
		node p = new node();
		p.v = v;
		p.cap = cap;
		p.next = head[u];
		head[u] = edges.size();
		edges.add(p);
	}

	public void add(int u, int v, int cap)
	{
		addEdge(u, v, cap);
		addEdge(v, u,0);
	}



	public int getMaxflow(int source, int sink)
	{
		for (int i = 0; i < vertexNum; ++ i) {
			cur[i] = head[i];
			num[i] = 0;
			h[i] = 0;
		}
		int u = source;
		int result = 0;
		while (h[u] < vertexNum)
		{
			if (u == sink)
			{
				int Min=Integer.MAX_VALUE;
				int v = -1;
				for (int i = source; i != sink; i = edges.get(cur[i]).v)
				{
					int k=cur[i];
					if(edges.get(k).cap < Min) {
						Min = edges.get(k).cap;
						v = i;
					}
				}
				result += Min;
				u=v;
				for (int i = source; i != sink; i = edges.get(cur[i]).v)
				{
					int k=cur[i];
					edges.get(k).cap -= Min;
					edges.get(k ^ 1).cap += Min;
				}
			}
			int index = -1;
			for (int i = cur[u]; i != -1; i = edges.get(i).next)
			{
				if (edges.get(i).cap > 0 && h[u] == h[edges.get(i).v] + 1) {
					index = i;
					break;
				}
			}
			if (index != -1)
			{
				cur[u] = index;
				pre[edges.get(index).v]=u;
				u=edges.get(index).v;
			}
			else
			{
				if (--num[h[u]] == 0) {
					break;
				}
				int k = vertexNum;
				cur[u] = head[u];
				for (int i = head[u]; i != -1; i = edges.get(i).next)
				{
					if(edges.get(i).cap>0 && h[edges.get(i).v] < k)
					{
						k = h[edges.get(i).v];
					}
				}
				if (k + 1 < vertexNum) {
					num[k + 1] += 1;
				}
				h[u] = k + 1;
				if (u != source) u=pre[u];
			}
		}
		return result;
	}
}

public class GreenWarfare {

	int p2(int x) {
		return x * x;
	}

	public int minimumEnergyCost(int[] canonX, int[] canonY, int[] baseX, int[] baseY,
															 int[] plantX, int[] plantY, int energySupplyRadius) {
		final int n = baseX.length;
		final int m = plantX.length;
		MaxFlow maxFlow = new MaxFlow(n + m + 2);
		for (int j = 0; j < m; ++ j) {
			int c = Integer.MAX_VALUE;
			for (int i = 0; i < canonX.length; ++ i) {
				c = Math.min(c, p2(canonX[i] - plantX[j]) + p2(canonY[i] - plantY[j]));
			}
			maxFlow.add(0, j + 1, c);
		}
		for (int j = 0; j < n; ++ j) {
			int c = Integer.MAX_VALUE;
			for (int i = 0; i < canonX.length; ++ i) {
				c = Math.min(c, p2(canonX[i] - baseX[j]) + p2(canonY[i] - baseY[j]));
			}
			maxFlow.add(m + j + 1, m + n + 1, c);
		}
		for (int i = 0; i < m; ++ i) {
			for (int j = 0; j < n; ++ j) {
				int d = p2(baseX[j] - plantX[i]) + p2(baseY[j] - plantY[i]);
				if ( d <= p2(energySupplyRadius)) {
					maxFlow.add(i + 1, m + j + 1, Integer.MAX_VALUE);
				}
			}
		}
		return maxFlow.getMaxflow(0, m + n + 1);
	}
}

  

code for problem3

import java.util.*;
import java.math.*;
import static java.lang.Math.*;

public class BouncingDiceGame {
	
	public double winProbability(int n, int d, int x, int y) {
		double[] p1 = cal(n, d, x);
		double[] p2 = cal(n, d, y);
		double[] p = new double[n];
		p[0] = 1;
		p[1] = (d - 1.0) / d;
		for (int i = 2; i < n; ++ i) {
			p[i] = p[i - 1] * p[1];
		}
		double result = 0;
		for (int i = 0; i < p1.length; ++ i) {
			for (int j = 0; j < p2.length; ++ j) {
				if (i < j) {
					result += p1[i] * p2[j] * (1 - p[j - i]);
				}
				result += p1[i] * p2[j] * p[Math.abs(i - j)] * d / (d + d - 1);
			}
		}
		return result;
	}
	double[] cal(int n, int d, int x) {
		if (x >= n - d) {
			double[] result = new double[1];
			result[0] = 1;
			return result;
		}
		final int m = n - d - x;
		double[] result = new double[m + 1];
		result[0] = 0;
		double[][] f = new double[2][n];
		for (int i = x; i <n; ++ i) {
			f[0][i] = 1;
		}
		int pre = 0;
		int cur = 1;
		for (int i = 1; i <= m; ++ i) {
			Arrays.fill(f[cur], 0);
			for (int j = x + 1; j < n; ++ j) {
				int rr = j - 1 >= n - d? n - d - 1 : j - 1;
				int ll = j - d - 1 >= 0? j - d - 1: 0;
				if (rr < ll) {
					continue;
				}
				f[cur][j] = (f[pre][rr] - f[pre][ll] ) / d;
			}
			for (int j = x; j < n; ++ j) {
				f[cur][j] += f[cur][j - 1];
			}
			result[i] = f[cur][n - 1] - f[cur][n - d - 1];
			pre ^= 1;
			cur ^= 1;
		}
		return result;
	}
}

  

posted @ 2017-11-04 17:52  朝拜明天19891101  阅读(307)  评论(0编辑  收藏  举报