100
1 0
1 0
1 0
1 0
1 0
1 1
1 0
1 0
1 0
1 1
1 0
1 0
1 0
1 0
1 0
1 0
1 0
1 0
1 1
1 0
1 0
1 0
1 0
1 1
1 0
1 1
1 0
1 1
1 1
1 0
1 0
1 0
1 1
1 0
1 0
1 0
1 1
1 1
1 0
1 1
1 0
1 1
1 1
1 0
1 0
1 0
1 0
1 1
1 0
1 0
1 0
1 0
1 1
1 0
1 0
1 1
1 0
1 0
1 0
1 1
1 0
1 1
1 0
1 0
1 0
1 0
1 0
1 0
1 0
1 0
1 0
1 0
1 0
1 0
1 1
1 0
1 1
1 0
1 0
1 1
1 1
1 0
1 0
1 1
1 0
1 0
1 1
1 1
1 1
1 0
1 0
1 1
1 0
1 0
1 1
1 0
1 0
1 0
1 0
1 0
 50
60 10
95 12
98 84
38 16
82 32
67 51
86 18
99 31
86 51
83 48
78 37
81 18
97 12
95 18
92 43
92 61
90 75
76 13
60 6
62 42
90 26
41 35
82 39
33 19
100 99
43 10
74 67
95 86
15 6
20 2
76 20
86 10
92 54
99 38
85 83
70 48
77 68
95 42
38 33
74 17
9 6
90 64
66 59
88 37
38 10
100 76
44 36
68 12
48 4
83 25
 10
1 1
1 0
1 0
1 1
1 0
1 1
1 0
1 1
1 0
1 1
 2
56 42
53 28
 3
1 1
1 0
1 0
 10
1 0
1 0
1 0
1 0
1 0
1 0
1 0
1 0
1 0
1 0
 20
13 12
64 18
72 50
69 69
79 21
68 45
99 29
74 47
18 16
57 19
14 10
75 67
39 38
64 0
53 35
84 76
76 59
78 21
7 1
85 43
 1
86 76

1.0000000000 2.0000000000 3.0000000000 4.0000000000 5.0000000000 6.0000000000 7.0000000000 8.0000000000 9.0000000000 10.0000000000 11.0000000000 12.0000000000 13.0000000000 14.0000000000 15.0000000000 16.0000000000 17.0000000000 18.0000000000 19.0000000000 20.0000000000 21.0000000000 22.0000000000 23.0000000000 24.0000000000 25.0000000000 26.0000000000 27.0000000000 28.0000000000 28.0000000000 28.0000000000 28.0000000000 28.0000000000 28.0000000000 28.0000000000 28.0000000000 28.0000000000 28.0000000000 28... 100.0000000000 200.0000000000 299.0000000000 398.0000000000 496.0000000000 593.0000000000 688.0000000000 783.0000000000 878.0000000000 973.0000000000 1065.0000000000 1157.0000000000 1247.0000000000 1324.0000000000 1382.0000000000 1429.5000000000 1460.5000000000 1484.0000000000 1505.0000000000 1524.5000000000 1543.5000000000 1562.0000000000 1580.5000000000 1598.5000000000 1616.0000000000 1632.5000000000 1648.5000000000 1664.0000000000 1677.0000000000 1689.5000000000 1699.5000000000 1709.0000000000 1718.0000... 1.0000000000 2.0000000000 3.0000000000 4.0000000000 5.0000000000 5.0000000000 5.0000000000 5.0000000000 5.0000000000 5.0000000000
 56.0000000000 70.0000000000
 1.0000000000 1.0000000000 1.0000000000
 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000
 99.0000000000 184.0000000000 268.0000000000 347.0000000000 425.0000000000 493.0000000000 536.5000000000 566.0000000000 585.0000000000 602.5000000000 617.0000000000 627.5000000000 638.0000000000 647.5000000000 656.5000000000 664.5000000000 670.5000000000 675.5000000000 676.0000000000 676.0000000000
 76.0000000000

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

public class D {
	FastScanner in;
	PrintWriter out;
	boolean systemIO = true;

	public class Pair implements Comparable<Pair> {
		int x;
		int y;

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

		public Pair clone() {
			return new Pair(x, y);
		}

		@Override
		public int compareTo(Pair o) {
			if (x > o.x) {
				return 1;
			}
			if (x < o.x) {
				return -1;
			}
			if (y > o.y) {
				return 1;
			}
			if (y < o.y) {
				return -1;
			}
			return 0;
		}

	}

	public class Fenvik {
		int[] sum;

		public Fenvik(int n) {
			sum = new int[n];
		}

		public void add(int x, int d) {
			for (int i = x; i < sum.length; i = (i | (i + 1))) {
				sum[i] += d;
			}
		}

		public int sum(int r) {
			int ans = 0;
			for (int i = r; i >= 0; i = (i & (i + 1)) - 1) {
				ans += sum[i];
			}
			return ans;
		}

		public int sum(int l, int r) {
			if (l > r) {
				return 0;
			}
			return sum(r) - sum(l - 1);
		}
	}
	
	public class SegmentTree {
		int pow;
		long[] min;

		public SegmentTree(long[] a) {
			pow = 1;
			while (pow < a.length) {
				pow *= 2;
			}
			min = new long[2 * pow];
			for (int i = 0; i < a.length; i++) {
				min[pow + i] = a[i];
			}
			for (int i = a.length; i < pow; i++) {
				min[pow + i] = Long.MAX_VALUE / 2;
			}
			for (int i = pow - 1; i > 0; i--) {
				min[i] = f(min[2 * i + 1], min[2 * i + 1]);
			}
		}

		public long get(int l, int r) {
			return get(1, 0, pow, l, r);
		}
		
		private long get(int v, int tl, int tr, int l, int r) {
			if (l >= tr || r <= tl) {
				return Long.MAX_VALUE / 2;
			}
			if (l <= tl && r >= tr) {
				return min[v];
			}
			int tm = (tl + tr) / 2;
			return f(get(2 * v, tl, tm, l, r), get(2 * v + 1, tm, tr, l, r));
		}

		public void set(int x, long value) {
			set(1, 0, pow, x, value);
		}
		
		private void set(int v, int tl, int tr, int x, long value) {
			if (x >= tr || x < tl) {
				return;
			}
			if (v >= pow) {
				min[v] = value;
				return;
			}
			int tm = (tl + tr) / 2;
			set(2 * v, tl, tm, x, value);
			set(2 * v + 1, tm, tr, x, value);
			min[v] = f(min[2 * v], min[2 * v + 1]);
		}

		public long f(long a, long b) {
			return Math.min(a, b);
		}
	}

	public long gcd(long x, long y) {
		if (y == 0) {
			return x;
		}
		if (x == 0) {
			return y;
		}
		return gcd(y, x % y);
	}

	public long[][] pow(long[][] x, long p) {
		if (p == 0) {
			long[][] ans = new long[x.length][x.length];
			for (int i = 0; i < ans.length; i++) {
				ans[i][i] = 1;
			}
			return ans;
		}
		long[][] t = pow(x, p / 2);
		t = multiply(t, t);
		if (p % 2 == 1) {
			t = multiply(t, x);
		}
		return t;
	}

	public long[][] multiply(long[][] a, long[][] b) {
		long[][] ans = new long[a.length][b[0].length];
		for (int i = 0; i < ans.length; i++) {
			for (int j = 0; j < ans[0].length; j++) {
				for (int k = 0; k < b.length; k++) {
					ans[i][j] += a[i][k] * b[k][j];
					ans[i][j] %= mod;
				}
			}
		}
		return ans;
	}

	public long pow(long x, long p) {
		if (p == 0) {
			return 1;
		}
		long t = pow(x, p / 2);
		t *= t;
		t %= mod;
		if (p % 2 == 1) {
			t *= x;
			t %= mod;
		}
		return t;
	}

	public long modInv(long x) {
		return pow(x, mod - 2);
	}

	long mod = 1000000007;

	public class VectorInt {
		long x;
		long y;

		public VectorInt(long x, long y) {
			this.x = x;
			this.y = y;
		}

		public VectorInt subtract(VectorInt v) {
			return new VectorInt(x - v.x, y - v.y);
		}

		public double norm() {
			return Math.sqrt(x * x + y * y);
		}
	}

	public class VectorDouble {
		double x;
		double y;

		public VectorDouble(double x, double y) {
			this.x = x;
			this.y = y;
		}

		public VectorDouble(VectorInt v) {
			x = v.x;
			y = v.y;
		}

		public String toString() {
			return x + " " + y;
		}

		public VectorDouble add(VectorDouble v) {
			return new VectorDouble(x + v.x, y + v.y);
		}

		public VectorDouble subtract(VectorDouble v) {
			return new VectorDouble(x - v.x, y - v.y);
		}

		public VectorDouble mult(double c) {
			return new VectorDouble(x * c, y * c);
		}

		public double norm() {
			return Math.sqrt(x * x + y * y);
		}

		public double norm2() {
			return x * x + y * y;
		}

		public void normalize() {
			double n = norm();
			x /= n;
			y /= n;
		}
	}

	public long dp(VectorInt a, VectorInt b) {
		return a.x * b.x + a.y * b.y;
	}

	public long cp(VectorInt a, VectorInt b) {
		return a.x * b.y - a.y * b.x;
	}

	public double dp(VectorDouble a, VectorDouble b) {
		return a.x * b.x + a.y * b.y;
	}

	public double cp(VectorDouble a, VectorDouble b) {
		return a.x * b.y - a.y * b.x;
	}

	Random random = new Random(566);

	public class Fret implements Comparable<Fret> {
		int value;
		int index;

		public Fret(int value, int index) {
			this.value = value;
			this.index = index;
		}

		@Override
		public int compareTo(Fret o) {
			if (value != o.value) {
				return value - o.value;
			}
			return index - o.index;
		}

	}

	public int[][] readGraph(int n, int m) {
		int[][] to = new int[n][];
		int[] sz = new int[n];
		int[] x = new int[m];
		int[] y = new int[m];
		for (int i = 0; i < m; i++) {
			x[i] = in.nextInt() - 1;
			y[i] = in.nextInt() - 1;
			sz[x[i]]++;
			sz[y[i]]++;
		}
		for (int i = 0; i < to.length; i++) {
			to[i] = new int[sz[i]];
			sz[i] = 0;
		}
		for (int i = 0; i < x.length; i++) {
			to[x[i]][sz[x[i]]++] = y[i];
			to[y[i]][sz[y[i]]++] = x[i];
		}
		return to;
	}

	public double volume(double x0, double y0, double dxdz, double dydz, double dz) {
		return x0 * y0 * dz - (dxdz * y0 + dydz * x0) * dz * dz / 2 + dxdz * dydz * dz * dz * dz / 3;
	}

	public class Vector {
		double x;
		double y;
		double z;

		public Vector(double x, double y, double z) {
			this.x = x;
			this.y = y;
			this.z = z;
		}

		public double norm() {
			return Math.sqrt(x * x + y * y + z * z);
		}

		public double norm2() {
			return x * x + y * y + z * z;
		}

		public Vector subtract(Vector v) {
			return new Vector(x - v.x, y - v.y, z - v.z);
		}
	}

	public Vector cp(Vector a, Vector b) {
		return new Vector(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
	}

	public double sin(Vector a, Vector b) {
		return cp(a, b).norm() / a.norm() / b.norm();
	}

	public double dp(Vector a, Vector b) {
		return a.x * b.x + a.y * b.y + a.z * b.z;
	}

	public double cos(Vector a, Vector b) {
		return dp(a, b) / a.norm() / b.norm();
	}

	double eps = 1e-9;

	int[] mult(int[] a, int[] b) {
		int[] res = new int[a.length];
		for (int i = 0; i < a.length; ++i) {
			res[i] = b[a[i]];
		}
		return res;
	}

	int[] rev(int[] a) {
		int[] res = new int[a.length];
		for (int i = 0; i < a.length; ++i) {
			res[a[i]] = i;
		}
		return res;
	}

	int[] conj(int[] pi, int[] f) {
		return mult(mult(rev(pi), f), pi);
	}

	void print(int[] p) {
		for (int i : p) {
			System.out.print(i + 1 + " ");
		}
		System.out.println();
	}

	public class Triangle implements Comparable<Triangle> {
		Pair p1;
		Pair p2;

		public Triangle(Pair p1, Pair p2) {
			this.p1 = p1.clone();
			this.p2 = p2.clone();
			if (p1.compareTo(p2) > 0) {
				Pair p = p1;
				this.p1 = p2;
				this.p2 = p;
			}
		}

		@Override
		public int compareTo(Triangle o) {
			if (p1.compareTo(o.p1) != 0) {
				return p1.compareTo(o.p1);
			}
			return p2.compareTo(o.p2);
		}

	}
	
	public class Color implements Comparable<Color> {
		int a;
		int b;
		
		public Color(int a, int b) {
			this.a = a;
			this.b = b;
		}
		
		public int day() {
			return a - b + 1;
		}

		@Override
		public int compareTo(Color o) {
			if (b == 0 && o.b == 0) {
				return 0;
			}
			if (b == 0) {
				return 1;
			}
			if (o.b == 0) {
				return -1;
			}
			return day() - o.day();
		}
		
	}

	public void solve() {
		int n = in.nextInt();
		int[] a = new int[n];
		int[] b = new int[n];
		int halfSum = 0;
		for (int i = 0; i < a.length; i++) {
			a[i] = in.nextInt();
			b[i] = in.nextInt();
			halfSum += b[i];
		}
		long time = System.currentTimeMillis();
		int maxSum = 100 * n + 1;
		int[][] dp = new int[n + 1][maxSum];
		boolean[][] can = new boolean[n + 1][maxSum];
		can[0][0] = true;
		for (int i = 0; i < n; i++) {
			for (int j = i; j >= 0; j--) {
				for (int k = 0; k < maxSum; k++) {
					if (can[j][k] && dp[j + 1][k + a[i]] <= dp[j][k] + b[i]) {
						can[j + 1][k + a[i]] = true;
						dp[j + 1][k + a[i]] = dp[j][k] + b[i];
					}
				}
			}
		}
		for (int i = 1; i <= n; i++) {
			int ans = 0;
			for (int j = 0; j < maxSum; j++) {
				if (can[i][j]) {
					int cur = Math.min(halfSum + dp[i][j], 2 * j);
					if (cur > ans) {
						ans = cur;
					}
				}
			}
			out.print(ans / 2.0 + " ");
		}
		System.err.println(System.currentTimeMillis() - time);
	}

	public void run() {
		try {
			if (systemIO) {
				in = new FastScanner(System.in);
				out = new PrintWriter(System.out);
			} else {
				in = new FastScanner(new File("input.txt"));
				out = new PrintWriter(new File("output.txt"));
			}
			solve();

			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		FastScanner(File f) {
			try {
				br = new BufferedReader(new FileReader(f));
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}

		FastScanner(InputStream f) {
			br = new BufferedReader(new InputStreamReader(f));
		}

		String nextLine() {
			try {
				return br.readLine();
			} catch (IOException e) {
				return null;
			}
		}

		String next() {
			while (st == null || !st.hasMoreTokens()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

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

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

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

	}

	// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
	public static void main(String[] arg) {
		long time = System.currentTimeMillis();
		new D().run();
//		System.err.println(System.currentTimeMillis() - time);
	}
}