import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Scanner;
import java.util.TreeMap;

public class Solution{

	///////////////////////////////////////////////////////////////////////////
	static class FastScanner{
		BufferedReader s;
		StringTokenizer st;

		public FastScanner(){
			st = new StringTokenizer("");
			s = new BufferedReader(new InputStreamReader(System.in));
		}

		public FastScanner(File f) throws FileNotFoundException{
			st = new StringTokenizer("");
			s = new BufferedReader (new FileReader(f));
		}

		public int nextInt() throws IOException{
			if(st.hasMoreTokens())
				return Integer.parseInt(st.nextToken());
			else{
				st = new StringTokenizer(s.readLine());
				return nextInt();
			}
		}

		public double nextDouble() throws IOException{
			if(st.hasMoreTokens())
				return Double.parseDouble(st.nextToken());
			else{
				st = new StringTokenizer(s.readLine());
				return nextDouble();
			}
		}

		public long nextLong() throws IOException{
			if(st.hasMoreTokens())
				return Long.parseLong(st.nextToken());
			else{
				st = new StringTokenizer(s.readLine());
				return nextLong();
			}
		}

		public String nextString() throws IOException{
			if(st.hasMoreTokens())
				return st.nextToken();
			else{
				st = new StringTokenizer(s.readLine());
				return nextString();
			}

		}
		public String readLine() throws IOException{
			return s.readLine();
		}

		public void close() throws IOException{
			s.close();
		}

	}

	////////////////////////////////////////////////////////////////////
	//		Number Theory

	public static int divisor(int x){
	    int limit = x;
	    int numberOfDivisors = 0;

	    for (int i=1; i < limit; ++i) {
	        if (x % i == 0) {
	            limit = x / i;
	            if (limit != i) {
	                numberOfDivisors++;
	            }
	            numberOfDivisors++;
	        }
	    }

	    return numberOfDivisors;
    }

	public static long gcd(long a, long b){
		return b == 0 ? a : gcd(b,a%b);
	}

	public static long lcm(long a,long b, long c){
		return lcm(lcm(a,b),c);
	}

	public static long lcm(long a, long b){
		return a*b/gcd(a,b);
	}

	////////////////////////////////////////////////////////////////////

//	  private static  	FastScanner s = new FastScanner(new File("input.txt"));
//	  private static PrintWriter ww = new PrintWriter(new FileWriter("output.txt"));
	  private static FastScanner s = new FastScanner();
      private static PrintWriter ww = new PrintWriter(new OutputStreamWriter(System.out));
//    private static Scanner s = new Scanner(System.in);
      @SuppressWarnings("unused")
	private static Map<Integer,Integer> mm = new HashMap<Integer,Integer>();
      @SuppressWarnings("unused")
	private static Map<Integer,node> mn = new HashMap<Integer,node>();
	@SuppressWarnings("unused")
	private static int[][] states = { {-1,0} , {1,0} , {0,-1} , {0,1} };

    ////////////////////////////////////////////////////////////////////

     static class node implements Comparable<node>{
      	int a;
      	int b;
      	public node(int x, int y){
      		this.a  = x;
      		this.b = y;
      	}
		@Override
		public int compareTo(node arg0) {
			// TODO Auto-generated method stub
			return Integer.compare(arg0.b, b);
		}
      }

    public static void main(String[] args) throws IOException{
 		Solution so = new Solution();
 		so.solve();
 	}

    ////////////////////////////////////////////////////////////////////

     void solve() throws IOException{

    	int n = s.nextInt();
    	node[] no = new node[n];
    	int sum = 0;
    	int gum = 0;
    	int ans = Integer.MAX_VALUE;

    	for(int i=0;i<n;i++){
    		int x = s.nextInt();
    		int y = s.nextInt();
    		no[i] = new node(x,y);
    		sum += y;
    	}

    	Arrays.sort(no);

    	for(int i=0;i<n;i++){
    		gum += no[i].a;
    		sum -= no[i].b;
    		if(gum >= sum){
    			ans = Math.min(ans,gum);
    			gum -= no[i].a;
    			sum += no[i].b;
    		}

    	}

    	ww.println(ans);
        s.close();
 	    ww.close();

     }
}


import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Scanner;
import java.util.TreeMap;

public class Solution{

	///////////////////////////////////////////////////////////////////////////
	static class FastScanner{
		BufferedReader s;
		StringTokenizer st;

		public FastScanner(){
			st = new StringTokenizer("");
			s = new BufferedReader(new InputStreamReader(System.in));
		}

		public FastScanner(File f) throws FileNotFoundException{
			st = new StringTokenizer("");
			s = new BufferedReader (new FileReader(f));
		}

		public int nextInt() throws IOException{
			if(st.hasMoreTokens())
				return Integer.parseInt(st.nextToken());
			else{
				st = new StringTokenizer(s.readLine());
				return nextInt();
			}
		}

		public double nextDouble() throws IOException{
			if(st.hasMoreTokens())
				return Double.parseDouble(st.nextToken());
			else{
				st = new StringTokenizer(s.readLine());
				return nextDouble();
			}
		}

		public long nextLong() throws IOException{
			if(st.hasMoreTokens())
				return Long.parseLong(st.nextToken());
			else{
				st = new StringTokenizer(s.readLine());
				return nextLong();
			}
		}

		public String nextString() throws IOException{
			if(st.hasMoreTokens())
				return st.nextToken();
			else{
				st = new StringTokenizer(s.readLine());
				return nextString();
			}

		}
		public String readLine() throws IOException{
			return s.readLine();
		}

		public void close() throws IOException{
			s.close();
		}

	}

	////////////////////////////////////////////////////////////////////
	//		Number Theory

	public static int divisor(int x){
	    int limit = x;
	    int numberOfDivisors = 0;

	    for (int i=1; i < limit; ++i) {
	        if (x % i == 0) {
	            limit = x / i;
	            if (limit != i) {
	                numberOfDivisors++;
	            }
	            numberOfDivisors++;
	        }
	    }

	    return numberOfDivisors;
    }

	public static long gcd(long a, long b){
		return b == 0 ? a : gcd(b,a%b);
	}

	public static long lcm(long a,long b, long c){
		return lcm(lcm(a,b),c);
	}

	public static long lcm(long a, long b){
		return a*b/gcd(a,b);
	}

	////////////////////////////////////////////////////////////////////

//	  private static  	FastScanner s = new FastScanner(new File("input.txt"));
//	  private static PrintWriter ww = new PrintWriter(new FileWriter("output.txt"));
	  private static FastScanner s = new FastScanner();
      private static PrintWriter ww = new PrintWriter(new OutputStreamWriter(System.out));
//    private static Scanner s = new Scanner(System.in);
      @SuppressWarnings("unused")
	private static Map<Integer,Integer> mm = new HashMap<Integer,Integer>();
      @SuppressWarnings("unused")
	private static Map<Integer,node> mn = new HashMap<Integer,node>();
	@SuppressWarnings("unused")
	private static int[][] states = { {-1,0} , {1,0} , {0,-1} , {0,1} };

    ////////////////////////////////////////////////////////////////////

     static class node implements Comparable<node>{
      	int a;
      	int b;
      	public node(int x, int y){
      		this.a  = x;
      		this.b = y;
      	}
		@Override
		public int compareTo(node arg0) {
			// TODO Auto-generated method stub
			return Integer.compare(arg0.b, b);
		}
      }

    public static void main(String[] args) throws IOException{
 		Solution so = new Solution();
 		so.solve();
 	}

    ////////////////////////////////////////////////////////////////////

     void solve() throws IOException{

    	int n = s.nextInt();
    	int[][] dp = new int[3][103];
    	int one = 0;
    	int two = 0;
    	int ans = Integer.MAX_VALUE;

    	for(int i=0;i<n;i++){
    		int x = s.nextInt();
    		if(x == 1) dp[1][one++] = s.nextInt();
    		else dp[2][two++] = s.nextInt();
    	}

    	Arrays.sort(dp[1],0,one);
    	Arrays.sort(dp[2],0,two);

    	for(int x=0;x<=one;x++){
    		for(int y=0;y<=two;y++){
    			int s = 0;
    			for(int i=0;i<one-x;i++)
    				s += dp[1][i];
    			for(int i=0;i<two-y;i++)
    				s += dp[2][i];
    			if(x+(2*y) >= s && ans > x+(y*2))
    				ans = x+(2*y);
    		}
    	}

    	ww.println(ans);
        s.close();
 	    ww.close();

     }
}


import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Scanner;
import java.util.TreeMap;

public class Solution{

	///////////////////////////////////////////////////////////////////////////
	static class FastScanner{
		BufferedReader s;
		StringTokenizer st;

		public FastScanner(){
			st = new StringTokenizer("");
			s = new BufferedReader(new InputStreamReader(System.in));
		}

		public FastScanner(File f) throws FileNotFoundException{
			st = new StringTokenizer("");
			s = new BufferedReader (new FileReader(f));
		}

		public int nextInt() throws IOException{
			if(st.hasMoreTokens())
				return Integer.parseInt(st.nextToken());
			else{
				st = new StringTokenizer(s.readLine());
				return nextInt();
			}
		}

		public double nextDouble() throws IOException{
			if(st.hasMoreTokens())
				return Double.parseDouble(st.nextToken());
			else{
				st = new StringTokenizer(s.readLine());
				return nextDouble();
			}
		}

		public long nextLong() throws IOException{
			if(st.hasMoreTokens())
				return Long.parseLong(st.nextToken());
			else{
				st = new StringTokenizer(s.readLine());
				return nextLong();
			}
		}

		public String nextString() throws IOException{
			if(st.hasMoreTokens())
				return st.nextToken();
			else{
				st = new StringTokenizer(s.readLine());
				return nextString();
			}

		}
		public String readLine() throws IOException{
			return s.readLine();
		}

		public void close() throws IOException{
			s.close();
		}

	}

	////////////////////////////////////////////////////////////////////
	//		Number Theory

	public static int divisor(int x){
	    int limit = x;
	    int numberOfDivisors = 0;

	    for (int i=1; i < limit; ++i) {
	        if (x % i == 0) {
	            limit = x / i;
	            if (limit != i) {
	                numberOfDivisors++;
	            }
	            numberOfDivisors++;
	        }
	    }

	    return numberOfDivisors;
    }

	public static long gcd(long a, long b){
		return b == 0 ? a : gcd(b,a%b);
	}

	public static long lcm(long a,long b, long c){
		return lcm(lcm(a,b),c);
	}

	public static long lcm(long a, long b){
		return a*b/gcd(a,b);
	}

	////////////////////////////////////////////////////////////////////

//	  private static  	FastScanner s = new FastScanner(new File("input.txt"));
//	  private static PrintWriter ww = new PrintWriter(new FileWriter("output.txt"));
	  private static FastScanner s = new FastScanner();
      private static PrintWriter ww = new PrintWriter(new OutputStreamWriter(System.out));
//    private static Scanner s = new Scanner(System.in);
      @SuppressWarnings("unused")
	private static Map<Integer,Integer> mm = new HashMap<Integer,Integer>();
      @SuppressWarnings("unused")
	private static Map<Integer,node> mn = new HashMap<Integer,node>();
	@SuppressWarnings("unused")
	private static int[][] states = { {-1,0} , {1,0} , {0,-1} , {0,1} };

    ////////////////////////////////////////////////////////////////////

     static class node implements Comparable<node>{
      	int a;
      	int b;
      	public node(int x, int y){
      		this.a  = x;
      		this.b = y;
      	}
		@Override
		public int compareTo(node arg0) {
			// TODO Auto-generated method stub
			return Integer.compare(arg0.b, b);
		}
      }

    public static void main(String[] args) throws IOException{
 		Solution so = new Solution();
 		so.solve();
 	}

    ////////////////////////////////////////////////////////////////////

     void solve() throws IOException{

    	int n = s.nextInt();
    	node[] no = new node[n];
    	int sum = 0;
    	int gum = 0;

    	for(int i=0;i<n;i++){
    		int x = s.nextInt();
    		int y = s.nextInt();
    		no[i] = new node(x,y);
    		sum += y;
    	}

    	Arrays.sort(no);

    	for(int i=0;i<n;i++){
    		gum += no[i].a;
    		sum -= no[i].b;
    		if(gum >= sum)
    			break;
    	}

    	ww.println(gum);
        s.close();
 	    ww.close();

     }
}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;

public class Bookshelf {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Throwable {
		boolean d = false;
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(in.readLine());
		Book[] bArr = new Book[n];
		for (int i = 0; i < n; i++) {
			bArr[i] = new Book(in.readLine());
		}
		Arrays.sort(bArr);

		if (d) System.out.println("#Sorted:");
		LinkedList<Book> bList = new LinkedList<Book>();
		for (Book b : bArr) {
			if (d) System.out.println(b);
			bList.add(b);
		}
		int vertical = 0;
		LinkedList<Book> vList = new LinkedList<Book>();
		int horizontal = 0;
		if (d) System.out.println("# running");
		for (int i = 0; i < n ; i++) {
			if (vertical - horizontal >= bList.getFirst().width) {
				if (d) System.out.println(bList.getFirst() + " -");
				horizontal += bList.removeFirst().width;
			} else {
				vertical += bList.getLast().thickness;
				if (d) System.out.println(bList.getLast() + " |");
				vList.addFirst(bList.removeLast());
			}
		}
		for (Book b: vList) {
			if ((vertical - b.thickness) - horizontal >= b.width) {
				horizontal += b.width;
				vertical -= b.thickness;
				if (d) System.out.println("# Post-add - : " + b);
			}
		}

		if (d) System.out.println("# horizontal - " + horizontal);
		System.out.println(vertical);

	}

}

class Book implements Comparable<Book>{
	int thickness = 0;
	int width = 0;

	public Book(String s) {
		String[] t = s.split(" ");
		this.thickness = Integer.parseInt(t[0]);
		this.width = Integer.parseInt(t[1]);
	}

	@Override
	public int compareTo(Book o) {
		int me = width * (3-thickness);
		int other = o.width * (3-o.thickness);

		return me - other;
	}

	public String toString() {
		return "# " + thickness + " " + width;
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class BShaassAndBookshelf {

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(in.readLine());
		int[] small = new int[100];
		int[] thick = new int[100];
		int smallCount = 0;
		int thickCount = 0;

		for (int i = 0; i < n; i++) {
			String[] parts = in.readLine().split(" ");
			if (parts[0].equals("1")) {
				small[smallCount++] = Integer.parseInt(parts[1]);
			} else {
				thick[thickCount++] = Integer.parseInt(parts[1]);
			}
		}

		Arrays.sort(small, 0, smallCount);
		Arrays.sort(thick, 0, thickCount);

		long ans = Long.MAX_VALUE;
		for (int smallTryC = 0; smallTryC <= smallCount; smallTryC++) {
			for (int thickTryC = 0; thickTryC <= thickCount; thickTryC++) {
				//try counts for standing books

				long totalThickness = smallTryC + 2*thickTryC;
				long totalLength = 0;

				for (int i = 0; i < smallCount - smallTryC; i++) {
					totalLength += small[i];
				}
				for (int i = 0; i < thickCount - thickTryC; i++) {
					totalLength += thick[i];
				}

				if (totalLength <= totalThickness && totalThickness < ans) {
					ans = totalThickness;
				}
			}
		}
		System.out.println(ans);

	}

}


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

import java.util.*;

//@SuppressWarnings("unused")
public class B {

	private final static boolean autoflush = false;

	private final static int INF = (int) 1e9;
	public B () {
		int N = sc.nextInt();
		List<Integer> LW1 = new ArrayList<Integer>();
		List<Integer> LW2 = new ArrayList<Integer>();

		for (int i : rep(N)) {
			int t = sc.nextInt();
			int w = sc.nextInt();
			if (t == 1)
				LW1.add(w);
			else
				LW2.add(w);
		}

		Integer [] W1 = LW1.toArray(new Integer[0]);
		Integer [] W2 = LW2.toArray(new Integer[0]);

		sort(W1); sort(W2);

		int L1 = W1.length, L2 = W2.length;

		int res = INF;
		for (int i : req(0, L1))
			for (int j : req(0, L2)) {
				int Y = 0;
				for (int m : rep(i))
					Y += W1[m];
				for (int m : rep(j))
					Y += W2[m];
				int Z = L1-i + 2*(L2-j);
				if (Z >= Y)
					res = min(res, Z);
			}

		exit(res);

	}

	////////////////////////////////////////////////////////////////////////////////////
	private static int [] rep(int N) { return rep(0, N); }
	private static int [] rep(int S, int T) { int [] res = new int [max(T-S, 0)]; for (int i = S; i < T; ++i) res[i-S] = i; return res; }
	private static int [] req(int S, int T) { return rep(S, T+1); }
	private static <T extends Comparable<T>> T max(T x, T y) { return x.compareTo(y) > 0 ? x : y; }
	////////////////////////////////////////////////////////////////////////////////////
	private final static MyScanner sc = new MyScanner();
	private static class MyScanner {
		private String next() {
			newLine();
			return line[index++];
		}
		private int nextInt() {
			return Integer.parseInt(next());
		}
		//////////////////////////////////////////////
		private boolean eol() {
			return index == line.length;
		}
		private String readLine() {
			try {
				return r.readLine();
			} catch (Exception e) {
				throw new Error (e);
			}
		}
		private final java.io.BufferedReader r;
		private MyScanner () {
			this(new java.io.BufferedReader(new java.io.InputStreamReader(System.in)));
		}
		private MyScanner (java.io.BufferedReader r) {
			try {
				this.r = r;
				while (!r.ready())
					Thread.sleep(1);
				start();
			} catch (Exception e) {
				throw new Error(e);
			}
		}
		private String [] line;
		private int index;
		private void newLine() {
			if (line == null || eol()) {
				line = readLine().split(" ");
				index = 0;
			}
		}
	}
	private static void print (Object o, Object... a) {
		printDelim(" ", o, a);
	}
	private static void printDelim (String delim, Object o, Object... a) {
		pw.println(build(delim, o, a));
	}
	private static void exit (Object o, Object... a) {
		print(o, a);
		exit();
	}
	private static void exit() {
		pw.close();
		System.out.flush();
		System.err.println("------------------");
		System.err.println("Time: " + ((millis() - t) / 1000.0));
		System.exit(0);
	}
	////////////////////////////////////////////////////////////////////////////////////
	private static String build (String delim, Object o, Object... a) {
		StringBuilder b = new StringBuilder();
		append(b, o, delim);
		for (Object p : a)
			append(b, p, delim);
		return b.toString().trim();
	}
	private static void append(StringBuilder b, Object o, String delim) {
		if (o.getClass().isArray()) {
			int L = java.lang.reflect.Array.getLength(o);
			for (int i : rep(L))
				append(b, java.lang.reflect.Array.get(o, i), delim);
		} else if (o instanceof Iterable<?>)
			for (Object p : (Iterable<?>)o)
				append(b, p, delim);
		else
			b.append(delim).append(o);
	}
	////////////////////////////////////////////////////////////////////////////////////
	private static void start() {
		t = millis();
	}
	private static java.io.PrintWriter pw = new java.io.PrintWriter(System.out, autoflush);
	private static long t;
	private static long millis() {
		return System.currentTimeMillis();
	}
	public static void main (String[] args) {
		new B();
		exit();
	}
}


import static java.lang.Math.*;
import static java.math.BigInteger.*;
import static java.util.Arrays.*;
import static java.util.Collections.*;

import java.math.*;
import java.util.*;

@SuppressWarnings("unused")
public class B {

	private final static boolean autoflush = false;

	private final static int MOD = (int) 1e9 + 7;
	private final static double eps = 1e-9;
	private final static int INF = (int) 1e9;

	public B () {
		int N = sc.nextInt();

		int [][] C = new int [101][3];
		for (int i : rep(N)) {
			int t = sc.nextInt();
			int w = sc.nextInt();
			++C[w][t];
		}

		int res = 0, L = 0;
		for (int w : req(1, 100))
			for (int t : req(1, 2))
				res += t * C[w][t];

		out: for (;;) {
			int X = INF, Y = INF, Z = INF;
			for (int w : req(1, 100))
				if (C[w][1] > 0) {
					X = w;
					if (C[w][1] > 1)
						Y = w;
					break;
				}
			if (Y == 0)
				for (int w : req(X+1, 100))
					if (C[w][1] > 0) {
						Y = w;
						break;
					}

			for (int w : req(1, 100))
				if (C[w][2] > 0) {
					Z = w;
					break;
				}

			if (X+Y <= Z) {
				if (L+X+Y <= res - 2) {
					--C[X][1]; --C[Y][1]; L += X+Y; res -= 2; continue out;
				}
			} else if (L+Z <= res - 2) {
				--C[Z][2]; L += Z; res -= 2; continue out;
			}

			if (L+X <= res - 1) {
				--C[X][1]; L += X; --res; continue out;
			}

			break;
		}

		exit(res);
	}

	////////////////////////////////////////////////////////////////////////////////////

	private static int [] rep(int N) { return rep(0, N); }
	private static int [] rep(int S, int T) { int [] res = new int [max(T-S, 0)]; for (int i = S; i < T; ++i) res[i-S] = i; return res; }
	private static int [] req(int S, int T) { return rep(S, T+1); }
	private static int [] sep(int N) { return sep(0, N); }
	private static int [] sep(int S, int T) { int [] res = new int [max(T-S, 0)]; for (int i = S; i < T; ++i) res[T-1-i] = i; return res; }
	private static int [] seq(int S, int T) { return sep(S, T+1); }
	private static int [] ccw (int [] D) { return new int [] { -D[1], D[0] }; }
	private static int [] cw (int [] D) { return new int [] { D[1], -D[0] }; }
	int [] digits(long N, int B, int sz) {
		int [] res = new int [sz];
		for (int i : sep(sz))
			if (N > 0) {
				res[i] = (int)(N % B);
				N /= B;
			}
		return res;
	}
	private static int digitSum(long N) {
		int res = 0;
		for (; N > 0; res += N % 10, N /= 10);
		return res;
	}
	private static <T extends Comparable<T>> T max(T x, T y) { return x.compareTo(y) > 0 ? x : y; }
	private static long mod(long x) { return mod(x, MOD); }
	private static long mod(long x, long mod) { return ((x % mod) + mod) % mod; }
	private static BigInteger BMOD = valueOf(MOD);
	private static long modPow(long b, long e) { return valueOf(b).modPow(valueOf(e), BMOD).longValue(); }
	private static long pow(long b, long e) { return round(Math.pow(b, e)); }
	private static String reverse (String S) { return new StringBuilder(S).reverse().toString(); }
	private static char [][] toCharArrays(String [] S) {
		int N = S.length;
		char [][] res = new char [N][];
		for (int i : rep(N))
			res[i] = S[i].toCharArray();
		return res;
	}
	////////////////////////////////////////////////////////////////////////////////////
	private final static MyScanner sc = new MyScanner();
	private static class MyScanner {
		private String next() {
			newLine();
			return line[index++];
		}
		private char nextChar() {
			return next().charAt(0);
		}
		private int nextInt() {
			return Integer.parseInt(next());
		}
		private long nextLong() {
			return Long.parseLong(next());
		}
		private double nextDouble() {
			return Double.parseDouble(next());
		}
		private String nextLine() {
			line = null;
			return readLine();
		}
		private String [] nextStrings() {
			line = null;
			return readLine().split(" ");
		}
		private char [] nextChars() {
			return next ().toCharArray ();
		}
		private Integer [] nextInts() {
			String [] L = nextStrings();
			Integer [] res = new Integer [L.length];
			for (int i : rep(L.length))
				res[i] = Integer.parseInt(L[i]);
			return res;
		}
		private Long [] nextLongs() {
			String [] L = nextStrings();
			Long [] res = new Long [L.length];
			for (int i : rep(L.length))
				res[i] = Long.parseLong(L[i]);
			return res;
		}
		private Double [] nextDoubles() {
			String [] L = nextStrings();
			Double [] res = new Double [L.length];
			for (int i : rep(L.length))
				res[i] = Double.parseDouble(L[i]);
			return res;
		}
		private String [] next (int N) {
			String [] res = new String [N];
			for (int i : rep(N))
				res[i] = next();
			return res;
		}
		private Integer [] nextInt (int N) {
			Integer [] res = new Integer [N];
			for (int i : rep(N))
				res[i] = nextInt();
			return res;
		}
		private Long [] nextLong (int N) {
			Long [] res = new Long [N];
			for (int i : rep(N))
				res[i] = nextLong();
			return res;
		}
		private Double [] nextDouble (int N) {
			Double [] res = new Double [N];
			for (int i : rep(N))
				res[i] = nextDouble();
			return res;
		}
		private String [][] nextStrings (int N) {
			String [][] res = new String [N][];
			for (int i : rep(N))
				res[i] = nextStrings();
			return res;
		}
		private Integer [][] nextInts (int N) {
			Integer [][] res = new Integer [N][];
			for (int i : rep(N))
				res[i] = nextInts();
			return res;
		}
		private Long [][] nextLongs (int N) {
			Long [][] res = new Long [N][];
			for (int i : rep(N))
				res[i] = nextLongs();
			return res;
		}
		private Double [][] nextDoubles (int N) {
			Double [][] res = new Double [N][];
			for (int i : rep(N))
				res[i] = nextDoubles();
			return res;
		}
		//////////////////////////////////////////////
		private boolean eol() {
			return index == line.length;
		}
		private String readLine() {
			try {
				return r.readLine();
			} catch (Exception e) {
				throw new Error (e);
			}
		}
		private final java.io.BufferedReader r;
		private MyScanner () {
			this(new java.io.BufferedReader(new java.io.InputStreamReader(System.in)));
		}
		private MyScanner (java.io.BufferedReader r) {
			try {
				this.r = r;
				while (!r.ready())
					Thread.sleep(1);
				start();
			} catch (Exception e) {
				throw new Error(e);
			}
		}
		private String [] line;
		private int index;
		private void newLine() {
			if (line == null || eol()) {
				line = readLine().split(" ");
				index = 0;
			}
		}
	}
	private static void print (Object o, Object... a) {
		printDelim(" ", o, a);
	}
	private static void cprint (Object o, Object... a) {
		printDelim("", o, a);
	}
	private static void printDelim (String delim, Object o, Object... a) {
		pw.println(build(delim, o, a));
	}
	private static void exit (Object o, Object... a) {
		print(o, a);
		exit();
	}
	private static void exit() {
		pw.close();
		System.out.flush();
		System.err.println("------------------");
		System.err.println("Time: " + ((millis() - t) / 1000.0));
		System.exit(0);
	}
	private static void NO() {
		throw new Error("NO!");
	}
	////////////////////////////////////////////////////////////////////////////////////
	private static String build (String delim, Object o, Object... a) {
		StringBuilder b = new StringBuilder();
		append(b, o, delim);
		for (Object p : a)
			append(b, p, delim);
		return b.toString().trim();
	}
	private static void append(StringBuilder b, Object o, String delim) {
		if (o.getClass().isArray()) {
			int L = java.lang.reflect.Array.getLength(o);
			for (int i : rep(L))
				append(b, java.lang.reflect.Array.get(o, i), delim);
		} else if (o instanceof Iterable<?>)
			for (Object p : (Iterable<?>)o)
				append(b, p, delim);
		else
			b.append(delim).append(o);
	}
	////////////////////////////////////////////////////////////////////////////////////
	private static void start() {
		t = millis();
	}
	private static java.io.PrintWriter pw = new java.io.PrintWriter(System.out, autoflush);
	private static long t;
	private static long millis() {
		return System.currentTimeMillis();
	}
	private static void statics() {
		abs(0); valueOf(0); asList(new Object [0]); reverseOrder();
	}
	public static void main (String[] args) {
		new B();
		exit();
	}
}


//@SuppressWarnings("unused")
public class B {

	private final static boolean autoflush = false;

	private final static int INF = (int) 1e9;

	public B () {
		int N = sc.nextInt();

		int [][] C = new int [101][3];
		for (int i : rep(N)) {
			int t = sc.nextInt();
			int w = sc.nextInt();
			++C[w][t];
		}

		int res = 0, L = 0;
		for (int w : req(1, 100))
			for (int t : req(1, 2))
				res += t * C[w][t];

		out: for (;;) {
			int X = INF, Y = INF, Z = INF;
			for (int w : req(1, 100))
				if (C[w][1] > 0) {
					X = w;
					if (C[w][1] > 1)
						Y = w;
					break;
				}
			if (Y == INF)
				for (int w : req(X+1, 100))
					if (C[w][1] > 0) {
						Y = w;
						break;
					}

			for (int w : req(1, 100))
				if (C[w][2] > 0) {
					Z = w;
					break;
				}

			if (X+Y < Z) {
				if (L+X+Y <= res - 2) {
					--C[X][1]; --C[Y][1]; L += X+Y; res -= 2; continue out;
				}
			} else if (L+Z <= res - 2) {
				--C[Z][2]; L += Z; res -= 2; continue out;
			}

			if (L+X <= res - 1) {
				--C[X][1]; L += X; --res; continue out;
			}

			break;
		}

		exit(res);
	}

	////////////////////////////////////////////////////////////////////////////////////

	private static int [] rep(int N) { return rep(0, N); }
	private static int [] rep(int S, int T) { int [] res = new int [max(T-S, 0)]; for (int i = S; i < T; ++i) res[i-S] = i; return res; }
	private static int [] req(int S, int T) { return rep(S, T+1); }
	private static <T extends Comparable<T>> T max(T x, T y) { return x.compareTo(y) > 0 ? x : y; }
	////////////////////////////////////////////////////////////////////////////////////
	private final static MyScanner sc = new MyScanner();
	private static class MyScanner {
		private String next() {
			newLine();
			return line[index++];
		}
		private int nextInt() {
			return Integer.parseInt(next());
		}
		//////////////////////////////////////////////
		private boolean eol() {
			return index == line.length;
		}
		private String readLine() {
			try {
				return r.readLine();
			} catch (Exception e) {
				throw new Error (e);
			}
		}
		private final java.io.BufferedReader r;
		private MyScanner () {
			this(new java.io.BufferedReader(new java.io.InputStreamReader(System.in)));
		}
		private MyScanner (java.io.BufferedReader r) {
			try {
				this.r = r;
				while (!r.ready())
					Thread.sleep(1);
				start();
			} catch (Exception e) {
				throw new Error(e);
			}
		}
		private String [] line;
		private int index;
		private void newLine() {
			if (line == null || eol()) {
				line = readLine().split(" ");
				index = 0;
			}
		}
	}
	private static void print (Object o, Object... a) {
		printDelim(" ", o, a);
	}
	private static void printDelim (String delim, Object o, Object... a) {
		pw.println(build(delim, o, a));
	}
	private static void exit (Object o, Object... a) {
		print(o, a);
		exit();
	}
	private static void exit() {
		pw.close();
		System.out.flush();
		System.err.println("------------------");
		System.err.println("Time: " + ((millis() - t) / 1000.0));
		System.exit(0);
	}
	////////////////////////////////////////////////////////////////////////////////////
	private static String build (String delim, Object o, Object... a) {
		StringBuilder b = new StringBuilder();
		append(b, o, delim);
		for (Object p : a)
			append(b, p, delim);
		return b.toString().trim();
	}
	private static void append(StringBuilder b, Object o, String delim) {
		if (o.getClass().isArray()) {
			int L = java.lang.reflect.Array.getLength(o);
			for (int i : rep(L))
				append(b, java.lang.reflect.Array.get(o, i), delim);
		} else if (o instanceof Iterable<?>)
			for (Object p : (Iterable<?>)o)
				append(b, p, delim);
		else
			b.append(delim).append(o);
	}
	////////////////////////////////////////////////////////////////////////////////////
	private static void start() {
		t = millis();
	}
	private static java.io.PrintWriter pw = new java.io.PrintWriter(System.out, autoflush);
	private static long t;
	private static long millis() {
		return System.currentTimeMillis();
	}
	public static void main (String[] args) {
		new B();
		exit();
	}
}


//@SuppressWarnings("unused")
public class B {

	private final static boolean autoflush = false;

	private final static int INF = (int) 1e9;

	public B () {
		int N = sc.nextInt();

		int [][] C = new int [101][3];
		for (int i : rep(N)) {
			int t = sc.nextInt();
			int w = sc.nextInt();
			++C[w][t];
		}

		int res = 0, L = 0;
		for (int w : req(1, 100))
			for (int t : req(1, 2))
				res += t * C[w][t];

		out: for (;;) {
			int X = INF, Y = INF, Z = INF;
			for (int w : req(1, 100))
				if (C[w][1] > 0) {
					X = w;
					if (C[w][1] > 1)
						Y = w;
					break;
				}
			if (Y == INF)
				for (int w : req(X+1, 100))
					if (C[w][1] > 0) {
						Y = w;
						break;
					}

			for (int w : req(1, 100))
				if (C[w][2] > 0) {
					Z = w;
					break;
				}

			if (X+Y <= Z) {
				if (L+X+Y <= res - 2) {
					--C[X][1]; --C[Y][1]; L += X+Y; res -= 2; continue out;
				}
			} else if (L+Z <= res - 2) {
				--C[Z][2]; L += Z; res -= 2; continue out;
			}

			if (L+X <= res - 1) {
				--C[X][1]; L += X; --res; continue out;
			}

			break;
		}

		exit(res);
	}

	////////////////////////////////////////////////////////////////////////////////////

	private static int [] rep(int N) { return rep(0, N); }
	private static int [] rep(int S, int T) { int [] res = new int [max(T-S, 0)]; for (int i = S; i < T; ++i) res[i-S] = i; return res; }
	private static int [] req(int S, int T) { return rep(S, T+1); }
	private static <T extends Comparable<T>> T max(T x, T y) { return x.compareTo(y) > 0 ? x : y; }
	////////////////////////////////////////////////////////////////////////////////////
	private final static MyScanner sc = new MyScanner();
	private static class MyScanner {
		private String next() {
			newLine();
			return line[index++];
		}
		private int nextInt() {
			return Integer.parseInt(next());
		}
		//////////////////////////////////////////////
		private boolean eol() {
			return index == line.length;
		}
		private String readLine() {
			try {
				return r.readLine();
			} catch (Exception e) {
				throw new Error (e);
			}
		}
		private final java.io.BufferedReader r;
		private MyScanner () {
			this(new java.io.BufferedReader(new java.io.InputStreamReader(System.in)));
		}
		private MyScanner (java.io.BufferedReader r) {
			try {
				this.r = r;
				while (!r.ready())
					Thread.sleep(1);
				start();
			} catch (Exception e) {
				throw new Error(e);
			}
		}
		private String [] line;
		private int index;
		private void newLine() {
			if (line == null || eol()) {
				line = readLine().split(" ");
				index = 0;
			}
		}
	}
	private static void print (Object o, Object... a) {
		printDelim(" ", o, a);
	}
	private static void printDelim (String delim, Object o, Object... a) {
		pw.println(build(delim, o, a));
	}
	private static void exit (Object o, Object... a) {
		print(o, a);
		exit();
	}
	private static void exit() {
		pw.close();
		System.out.flush();
		System.err.println("------------------");
		System.err.println("Time: " + ((millis() - t) / 1000.0));
		System.exit(0);
	}
	////////////////////////////////////////////////////////////////////////////////////
	private static String build (String delim, Object o, Object... a) {
		StringBuilder b = new StringBuilder();
		append(b, o, delim);
		for (Object p : a)
			append(b, p, delim);
		return b.toString().trim();
	}
	private static void append(StringBuilder b, Object o, String delim) {
		if (o.getClass().isArray()) {
			int L = java.lang.reflect.Array.getLength(o);
			for (int i : rep(L))
				append(b, java.lang.reflect.Array.get(o, i), delim);
		} else if (o instanceof Iterable<?>)
			for (Object p : (Iterable<?>)o)
				append(b, p, delim);
		else
			b.append(delim).append(o);
	}
	////////////////////////////////////////////////////////////////////////////////////
	private static void start() {
		t = millis();
	}
	private static java.io.PrintWriter pw = new java.io.PrintWriter(System.out, autoflush);
	private static long t;
	private static long millis() {
		return System.currentTimeMillis();
	}
	public static void main (String[] args) {
		new B();
		exit();
	}
}


// @author Sanzhar
import java.io.*;
import java.util.*;
import java.awt.Point;

public class Template {

    BufferedReader in;
    PrintWriter out;
    StringTokenizer st;

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

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

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

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

    public void run() throws Exception {
        //in = new BufferedReader(new FileReader("passwords.in"));
        //out = new PrintWriter(new FileWriter("passwords.out"));
        in = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out);
        solve();
        out.flush();
        out.close();
        in.close();
    }

    public void solve() throws Exception {
        int n = nextInt();
        int[] w1 = new int[n + 1];
        int[] w2 = new int[n + 1];
        int k1 = 0, k2 = 0;
        for (int i = 0; i < n; i++) {
            int t = nextInt();
            if (t == 1) {
                w1[k1++] = nextInt();
            } else {
                w2[k2++] = nextInt();
            }
        }
        Arrays.sort(w1, 0, k1);
        Arrays.sort(w2, 0, k2);
        int ans = 202;
        for (int x = 0; x <= k1; x++) {
            for (int y = 0; y <= k2; y++) {
                int z = x + 2 * y;
                int zz = 0;
                for (int i = 0; i < k1 - x; i++) {
                    zz += w1[i];
                }
                for (int i = 0; i < k2 - y; i++) {
                    zz += w2[i];
                }
                if (z >= zz) {
                    ans = Math.min(z, ans);
                }
                //System.err.println(x + " " + y + " " + z + " " + zz);
            }
        }
        out.println(ans);
    }

    public static void main(String[] args) throws Exception {
        new Template().run();
    }
}


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class B294 {

    public static void main(String[] args) {
        List<Integer> ones = new ArrayList<Integer>();
        List<Integer> twos = new ArrayList<Integer>();

        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int sumone = 0;
        int sumtwo = 0;

        for (int i = 0; i < n; i++) {
            if (sc.nextInt() == 1) {
                int value = sc.nextInt();
                ones.add(value);
                sumone += value;
            } else {
                int value = sc.nextInt();
                twos.add(value);
                sumtwo += value;
            }
        }
        Collections.sort(ones);
        Collections.sort(twos);

        Collections.reverse(ones);
        Collections.reverse(twos);

        int v1 = ones.size();
        int v2 = twos.size();

        int minlen = Integer.MAX_VALUE;

        if (v1 > 0) {
            int oneslen = sumone;
            for (int k = 0; k <= v1; k++) {
                if( k != 0 )
                    oneslen -= ones.get(k-1);

                int twoslen = sumtwo;
                for(int j = 0; j <= v2; j++){
                    if( j != 0)
                        twoslen -= twos.get(j-1);

                    int vert = k + j * 2;

                    if(oneslen + twoslen <= vert)
                    {
                        if(vert < minlen) minlen = vert;
                    }
                }
            }
        }else{ // v2 > 0
            int twoslen = sumtwo;
            for(int j = 0; j <= v2; j++){
                if( j != 0)
                    twoslen -= twos.get(j-1);

                int oneslen = sumone;
                for (int k = 0; k <= v1; k++) {
                    if( k != 0 )
                        oneslen -= ones.get(k-1);

                    int vert = k + j * 2;

                    if(oneslen + twoslen <= vert)
                    {
                        if(vert < minlen) minlen = vert;
                    }
                }
            }
        }
        System.out.println(minlen);
    }
}


//select minimum thinkness t of k books such that sum of width of unselected items w <=t
import java.util.*;
public final class Bookshelf
{
	public static void main(String[] args) {
		Scanner br=new Scanner(System.in);
		int n=br.nextInt();
		Integer[] a=new Integer[n];
		Integer[] b=new Integer[n];
		int j=0,k=0,ans=9999999;
		for(int i=0;i<n;i++)
	{		int t=br.nextInt();
			int w=br.nextInt();
			if(t==1)
			a[j++]=w;
		else
			b[k++]=w;
	}
	j--;k--;
	Arrays.sort(a,0,j+1, Collections.reverseOrder());
	Arrays.sort(b,0,k+1, Collections.reverseOrder());
	int[] sum=new int[j+2];
	int[] sum2=new int[k+2];
	sum[j]=a[j];
	for(int i=j-1;i>=0;i--)
		sum[i]+=a[i]+sum[i+1];
	sum2[k]=b[k];
	for(int i=k-1;i>=0;i--)
		sum2[i]+=b[i]+sum2[i+1];
	for(int i=0;i<=j;i++)
	{
		for(int l=0;l<=k;l++)
		{
			if((l+1)*2+(i+1)>=sum[i+1]+sum2[l+1] && (l+1)*2+(i+1)<ans)
				{
					ans=(l+1)*2+(i+1);

				}
		}
	}
	System.out.println(ans);

	}
}


//select minimum thinkness t of k books such that sum of width of unselected items w <=t
import java.util.*;
public final class Bookshelf
{
	public static void main(String[] args) {
		Scanner br=new Scanner(System.in);
		int n=br.nextInt();
		Integer[] a=new Integer[n+2];
		Integer[] b=new Integer[n+2];
		int j=1,k=1,ans=9999999;
		for(int i=0;i<n;i++)
	{		int t=br.nextInt();
			int w=br.nextInt();
			if(t==1)
			a[j++]=w;
		else
			b[k++]=w;
	}
	if(n==1)
	{
		System.out.println(j>1?1:2);
		System.exit(0);
	}
	Arrays.sort(a,1,j, Collections.reverseOrder());
	Arrays.sort(b,1,k, Collections.reverseOrder());
	j--;k--;
	int[] sum=new  int[j+2];
	int[] sum2=new int[k+2];
	sum[j]=a[j];
	for(int i=j-1;i>=1;i--)
		sum[i]+=a[i]+sum[i+1];
	sum2[k]=b[k];
	for(int i=k-1;i>=1;i--)
		sum2[i]+=b[i]+sum2[i+1];
	for(int i=0;i<=j;i++)
	{
		for(int l=0;l<=k;l++)
		{
			if(i==0 && l==0)
				continue;
			else if(i==0 && l*2>=sum[1]+sum2[l+1] && l*2<ans)
				ans=l*2;
			else if(l==0 && i>=sum[i+1]+sum2[1] && i<ans)
				ans=i;
			else if(l*2+i>=sum[i+1]+sum2[l+1] && l*2+i<ans)
				{
					ans=l*2+i;

				}
		}
	}
	System.out.println(ans);

	}
}


//select minimum thinkness t of k books such that sum of width of unselected items w <=t
import java.util.*;
public final class Bookshelf
{
	public static void main(String[] args) {
		Scanner br=new Scanner(System.in);
		int n=br.nextInt();
		Integer[] a=new Integer[n];
		Integer[] b=new Integer[n];
		int j=0,k=0,ans=9999999;
		for(int i=0;i<n;i++)
	{		int t=br.nextInt();
			int w=br.nextInt();
			if(t==1)
			a[j++]=w;
		else
			b[k++]=w;
	}
	if(n==1)
	{
		System.out.println(j>0?1:2);
		System.exit(0);
	}
	j--;k--;
	Arrays.sort(a,0,j+1, Collections.reverseOrder());
	Arrays.sort(b,0,k+1, Collections.reverseOrder());
	int[] sum=new int[j+2];
	int[] sum2=new int[k+2];
	sum[j]=a[j];
	for(int i=j-1;i>=0;i--)
		sum[i]+=a[i]+sum[i+1];
	sum2[k]=b[k];
	for(int i=k-1;i>=0;i--)
		sum2[i]+=b[i]+sum2[i+1];
	for(int i=0;i<=j;i++)
	{
		for(int l=0;l<=k;l++)
		{
			if((l+1)*2+(i+1)>=sum[i+1]+sum2[l+1] && (l+1)*2+(i+1)<ans)
				{
					ans=(l+1)*2+(i+1);

				}
		}
	}
	System.out.println(ans);

	}
}


//select minimum thinkness t of k books such that sum of width of unselected items w <=t
import java.util.*;
public final class Bookshelf
{
	public static void main(String[] args) {
		Scanner br=new Scanner(System.in);
		int n=br.nextInt();
		Integer[] a=new Integer[n+2];
		Integer[] b=new Integer[n+2];
		int j=1,k=1,ans=9999999;
		for(int i=0;i<n;i++)
	{		int t=br.nextInt();
			int w=br.nextInt();
			if(t==1)
			a[j++]=w;
		else
			b[k++]=w;
	}
	if(n==1)
	{
		System.out.println(j>1?1:2);
		System.exit(0);
	}
	Arrays.sort(a,1,j, Collections.reverseOrder());
	Arrays.sort(b,1,k, Collections.reverseOrder());
	j--;k--;
	int[] sum=new  int[n+2];
	int[] sum2=new int[n+2];
	if(j>0)
	sum[j]=a[j];
	for(int i=j-1;i>=1;i--)
		sum[i]+=a[i]+sum[i+1];
	if(k>0)
	sum2[k]=b[k];
	for(int i=k-1;i>=1;i--)
		sum2[i]+=b[i]+sum2[i+1];
	for(int i=0;i<=j;i++)
	{
		for(int l=0;l<=k;l++)
		{
			if(i==0 && l==0)
				continue;
			else if(i==0 && l*2>=sum[1]+sum2[l+1] && l*2<ans)
				ans=l*2;
			else if(l==0 && i>=sum[i+1]+sum2[1] && i<ans)
				ans=i;
			else if(l*2+i>=sum[i+1]+sum2[l+1] && l*2+i<ans)
				{
					ans=l*2+i;

				}
		}
	}
	System.out.println(ans);

	}
}


//select minimum thinkness t of k books such that sum of width of unselected items w <=t
import java.util.*;
public final class Bookshelf
{
	public static void main(String[] args) {
		Scanner br=new Scanner(System.in);
		int n=br.nextInt();
		Integer[] a=new Integer[n+2];
		Integer[] b=new Integer[n+2];
		int j=1,k=1,ans=9999999;
		for(int i=0;i<n;i++)
	{		int t=br.nextInt();
			int w=br.nextInt();
			if(t==1)
			a[j++]=w;
		else
			b[k++]=w;
	}
	if(n==1)
	{
		System.out.println(j>1?1:2);
		System.exit(0);
	}
	Arrays.sort(a,1,j, Collections.reverseOrder());
	Arrays.sort(b,1,k, Collections.reverseOrder());
	j--;k--;
	int[] sum=new  int[n+2];
	int[] sum2=new int[n+2];
	if(j>1)
	sum[j]=a[j];
	for(int i=j-1;i>=1;i--)
		sum[i]+=a[i]+sum[i+1];
	if(k>1)
	sum2[k]=b[k];
	for(int i=k-1;i>=1;i--)
		sum2[i]+=b[i]+sum2[i+1];
	for(int i=0;i<=j;i++)
	{
		for(int l=0;l<=k;l++)
		{
			if(i==0 && l==0)
				continue;
			else if(i==0 && l*2>=sum[1]+sum2[l+1] && l*2<ans)
				ans=l*2;
			else if(l==0 && i>=sum[i+1]+sum2[1] && i<ans)
				ans=i;
			else if(l*2+i>=sum[i+1]+sum2[l+1] && l*2+i<ans)
				{
					ans=l*2+i;

				}
		}
	}
	System.out.println(ans);

	}
}


//select minimum thinkness t of k books such that sum of width of unselected items w <=t
import java.util.*;
public final class Bookshelf
{
	public static void main(String[] args) {
		Scanner br=new Scanner(System.in);
		int n=br.nextInt();
		Integer[] a=new Integer[n];
		Integer[] b=new Integer[n];
		int j=1,k=1,ans=9999999;
		for(int i=0;i<n;i++)
	{		int t=br.nextInt();
			int w=br.nextInt();
			if(t==1)
			a[j++]=w;
		else
			b[k++]=w;
	}
	if(n==1)
	{
		System.out.println(j>0?1:2);
		System.exit(0);
	}
	Arrays.sort(a,1,j, Collections.reverseOrder());
	Arrays.sort(b,1,k, Collections.reverseOrder());
	j--;k--;
	int[] sum=new  int[j+2];
	int[] sum2=new int[k+2];
	sum[j]=a[j];
	for(int i=j-1;i>=1;i--)
		sum[i]+=a[i]+sum[i+1];
	sum2[k]=b[k];
	for(int i=k-1;i>=1;i--)
		sum2[i]+=b[i]+sum2[i+1];
	for(int i=0;i<=j;i++)
	{
		for(int l=0;l<=k;l++)
		{
			if(i==0 && l==0)
				continue;
			else if(i==0 && l*2>=sum[1]+sum2[l+1] && l*2<ans)
				ans=l*2;
			else if(l==0 && i>=sum[i+1]+sum2[1] && i<ans)
				ans=i;
			else if(l*2+i>=sum[i+1]+sum2[l+1] && l*2+i<ans)
				{
					ans=l*2+i;

				}
		}
	}
	System.out.println(ans);

	}
}


//select minimum thinkness t of k books such that sum of width of unselected items w <=t
import java.util.*;
public final class Bookshelf
{
	public static void main(String[] args) {
		Scanner br=new Scanner(System.in);
		int n=br.nextInt();
		Integer[] a=new Integer[n];
		Integer[] b=new Integer[n];
		int j=0,k=0,ans=0;
		for(int i=0;i<n;i++)
	{		int t=br.nextInt();
			int w=br.nextInt();
			if(t==1)
			a[j++]=w;
		else
			b[k++]=w;
	}
	j--;k--;
	Arrays.sort(a,0,j+1, Collections.reverseOrder());
	Arrays.sort(b,0,k+1, Collections.reverseOrder());
	int[] sum=new int[j+2];
	int[] sum2=new int[k+2];
	sum[j]=a[j];
	for(int i=j-1;i>=0;i--)
		sum[i]+=a[i]+sum[i+1];
	sum2[k]=b[k];
	for(int i=k-1;i>=0;i--)
		sum2[i]+=b[i]+sum2[i+1];
	for(int i=0;i<=j && ans==0;i++)
	{
		for(int l=0;l<=k;l++)
		{
			if((l+1)*2+(i+1)>=sum[i+1]+sum2[l+1])
				{
					ans=(l+1)*2+(i+1);
					break;

				}
		}
	}
	System.out.println(ans);

	}
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class CF {
    FastScanner in;
    PrintWriter out;

    void solve() {
        int n = in.nextInt();
        ArrayList<Integer> t1 = new ArrayList<>();
        ArrayList<Integer> t2 = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            int t = in.nextInt();
            if (t == 1) {
                t1.add(in.nextInt());
            } else {
                t2.add(in.nextInt());
            }
        }
        int ans = Integer.MAX_VALUE;
        Collections.sort(t1);
        Collections.sort(t2);
        for (int f = 0; f <= t1.size(); f++)
            for (int s = 0; s <= t2.size(); s++) {
                int len = f + s * 2;
                int sum = 0;
                for (int j = 0; j < t1.size(); j++)
                    if (j + f < t1.size())
                        sum += t1.get(j);
                for (int j = 0; j < t2.size(); j++)
                    if (j + s < t2.size())
                        sum += t2.get(j);
                if (sum <= len) {
                    ans = Math.min(ans, len);
                }
            }

        out.println(ans);
    }

    void run() {
        try {
            in = new FastScanner(new File("test.in"));
            out = new PrintWriter(new File("test.out"));

            solve();

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

    void runIO() {
        in = new FastScanner(System.in);
        out = new PrintWriter(System.out);

        solve();

        out.close();
    }

    class FastScanner {
        BufferedReader br;
        StringTokenizer st;

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

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

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

        boolean hasMoreTokens() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return false;
                st = new StringTokenizer(s);
            }
            return true;
        }

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

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

    public static void main(String[] args) {
        new CF().runIO();
    }
}


import java.io.*;
import java.math.*;
import static java.lang.Math.*;
import java.security.SecureRandom;
import static java.util.Arrays.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import sun.misc.Regexp;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import sun.net.www.content.text.plain;

public class Main {
    static double EPS=pow(10,-9);
    public static void main(String[] args) throws IOException {
        new Main().run();
    }
    StreamTokenizer in;
    PrintWriter out;
//deb////////////////////////////////////////////////

    public static void deb(String n, Object n1) {
        System.out.println(n + " is : " + n1);
    }

    public static void deb(int[] A) {

        for (Object oo : A) {
            System.out.print(oo + " ");
        }
        System.out.println("");
    }

    public static void deb(long[] A) {

        for (Object oo : A) {
            System.out.print(oo + " ");
        }
        System.out.println("");
    }

    public static void deb(boolean[] A) {

        for (Object oo : A) {
            System.out.print(oo + " ");
        }
        System.out.println("");
    }

    public static void deb(double[] A) {

        for (Object oo : A) {
            System.out.print(oo + " ");
        }
        System.out.println("");
    }

    public static void deb(String[] A) {

        for (Object oo : A) {
            System.out.print(oo + " ");
        }
        System.out.println("");
    }

    public static void deb(int[][] A) {
        for (int i = 0; i < A.length; i++) {
            for (Object oo : A[i]) {
                System.out.print(oo + " ");
            }
            System.out.println("");
        }

    }

    public static void deb(double[][] A) {
        for (int i = 0; i < A.length; i++) {
            for (Object oo : A[i]) {
                System.out.print(oo + " ");
            }
            System.out.println("");
        }

    }

    public static void deb(long[][] A) {
        for (int i = 0; i < A.length; i++) {
            for (Object oo : A[i]) {
                System.out.print(oo + " ");
            }
            System.out.println("");
        }

    }

    public static void deb(String[][] A) {
        for (int i = 0; i < A.length; i++) {
            for (Object oo : A[i]) {
                System.out.print(oo + " ");
            }
            System.out.println("");
        }

    }
    /////////////////////////////////////////////////////////////

    int nextInt() throws IOException {
        in.nextToken();
        return (int) in.nval;
    }

    long nextLong() throws IOException {
        in.nextToken();
        return (long) in.nval;
    }

    void run() throws IOException {
//          in = new StreamTokenizer(new BufferedReader(new FileReader("input.txt")));
        // out = new PrintWriter(new FileWriter("output.txt"));
        in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(new OutputStreamWriter(System.out));
        solve();
        out.flush();
    }
//boolean inR(int x,int y){
//return (x<=0)&&(x<4)&&(y<=0)&&(y<4);
//}

    @SuppressWarnings("unchecked")
    void solve() throws IOException {
        //   BufferedReader re= new BufferedReader(new FileReader("C:\\Users\\ASELA\\Desktop\\PROBLEMSET\\input\\F\\10.in"));
   //           BufferedReader re = new BufferedReader(new InputStreamReader(System.in));
  //  Scanner sc= new Scanner(System.in);
 int N=nextInt();
 ArrayList<Integer> ts1=new ArrayList<Integer>();
  ArrayList<Integer> ts2=new ArrayList<Integer>();
  int tot=0,wid=0;
        for (int i = 0; i < N; i++) {
            if(nextInt()==1){
                int k=nextInt();
                tot+=k;
                ts1.add(k);}
            else {
                int k=nextInt();
                tot+=k;
                ts2.add(k);}
        }
        Collections.sort(ts2);
        Collections.sort(ts1);
  int[] one=new int[ts1.size()+1];
  int[] two=new int[ts2.size()+1];
  int l1=ts1.size(),l2=ts2.size();
  one[0]=0;
  two[0]=0;
        for (int i = 1; i <= l1; i++) {
            one[i]=one[i-1]+ts1.get(l1-i);
        }
         for (int i = 1; i <= l2; i++) {
            two[i]=two[i-1]+ts2.get(l2-i);
        }
         int minw=10000000;

        for (int i = 0; i <= l1; i++) {
            for (int j = 0; j <= l2; j++) {
             if(tot-one[i]-two[j]<=i+2*j){
             if(i+2*j<minw)minw=i+2*j;
             }
            }
        }
        System.out.println(minw);
    }

}
class node{
int parent=-1;
    TreeSet<Integer> children= new TreeSet<Integer>();

}


import java.io.*;
import java.math.*;
import static java.lang.Math.*;
import java.security.SecureRandom;
import static java.util.Arrays.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import sun.misc.Regexp;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import sun.net.www.content.text.plain;

public class Main {
    static double EPS=pow(10,-9);
    public static void main(String[] args) throws IOException {
        new Main().run();
    }
    StreamTokenizer in;
    PrintWriter out;
//deb////////////////////////////////////////////////

    public static void deb(String n, Object n1) {
        System.out.println(n + " is : " + n1);
    }

    public static void deb(int[] A) {

        for (Object oo : A) {
            System.out.print(oo + " ");
        }
        System.out.println("");
    }

    public static void deb(long[] A) {

        for (Object oo : A) {
            System.out.print(oo + " ");
        }
        System.out.println("");
    }

    public static void deb(boolean[] A) {

        for (Object oo : A) {
            System.out.print(oo + " ");
        }
        System.out.println("");
    }

    public static void deb(double[] A) {

        for (Object oo : A) {
            System.out.print(oo + " ");
        }
        System.out.println("");
    }

    public static void deb(String[] A) {

        for (Object oo : A) {
            System.out.print(oo + " ");
        }
        System.out.println("");
    }

    public static void deb(int[][] A) {
        for (int i = 0; i < A.length; i++) {
            for (Object oo : A[i]) {
                System.out.print(oo + " ");
            }
            System.out.println("");
        }

    }

    public static void deb(double[][] A) {
        for (int i = 0; i < A.length; i++) {
            for (Object oo : A[i]) {
                System.out.print(oo + " ");
            }
            System.out.println("");
        }

    }

    public static void deb(long[][] A) {
        for (int i = 0; i < A.length; i++) {
            for (Object oo : A[i]) {
                System.out.print(oo + " ");
            }
            System.out.println("");
        }

    }

    public static void deb(String[][] A) {
        for (int i = 0; i < A.length; i++) {
            for (Object oo : A[i]) {
                System.out.print(oo + " ");
            }
            System.out.println("");
        }

    }
    /////////////////////////////////////////////////////////////

    int nextInt() throws IOException {
        in.nextToken();
        return (int) in.nval;
    }

    long nextLong() throws IOException {
        in.nextToken();
        return (long) in.nval;
    }

    void run() throws IOException {
//          in = new StreamTokenizer(new BufferedReader(new FileReader("input.txt")));
        // out = new PrintWriter(new FileWriter("output.txt"));
        in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(new OutputStreamWriter(System.out));
        solve();
        out.flush();
    }
//boolean inR(int x,int y){
//return (x<=0)&&(x<4)&&(y<=0)&&(y<4);
//}

    @SuppressWarnings("unchecked")
    void solve() throws IOException {
        //   BufferedReader re= new BufferedReader(new FileReader("C:\\Users\\ASELA\\Desktop\\PROBLEMSET\\input\\F\\10.in"));
   //           BufferedReader re = new BufferedReader(new InputStreamReader(System.in));
  //  Scanner sc= new Scanner(System.in);
 int N=nextInt();
 ArrayList<Integer> ts1=new ArrayList<Integer>();
  ArrayList<Integer> ts2=new ArrayList<Integer>();
  int tot=0,wid=0;
        for (int i = 0; i < N; i++) {
            if(nextInt()==1){
                int k=nextInt();
                tot+=k;
                ts1.add(k);}
            else {
                int k=nextInt();
                tot+=k;
                ts2.add(k);}
        }
        Collections.sort(ts2);
        Collections.sort(ts1);
    while(tot>wid){
    if(ts1.isEmpty()){
    wid+=2;
    tot-=ts2.get(ts2.size()-1);
    ts2.remove(ts2.size()-1);
    continue;
    }
     if(ts2.isEmpty()){
    wid+=1;
    tot-=ts1.get(ts1.size()-1);
    ts1.remove(ts1.size()-1);
    continue;
    }
     int a1=ts2.get(ts2.size()-1),a2=ts1.get(ts1.size()-1);;
    if(a2>a1+1){
    wid+=1;
    tot-=ts1.get(ts1.size()-1);
    ts1.remove(ts1.size()-1);
    continue;

    }
    else{
    wid+=2;
    tot-=ts2.get(ts2.size()-1);
    ts2.remove(ts2.size()-1);
    continue;

    }
    }
        System.out.println(wid);
    }

}
class node{
int parent=-1;
    TreeSet<Integer> children= new TreeSet<Integer>();

}


import java.io.*;
import java.math.*;
import static java.lang.Math.*;
import java.security.SecureRandom;
import static java.util.Arrays.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import sun.misc.Regexp;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import sun.net.www.content.text.plain;

public class Main {
    static double EPS=pow(10,-9);
    public static void main(String[] args) throws IOException {
        new Main().run();
    }
    StreamTokenizer in;
    PrintWriter out;
//deb////////////////////////////////////////////////

    public static void deb(String n, Object n1) {
        System.out.println(n + " is : " + n1);
    }

    public static void deb(int[] A) {

        for (Object oo : A) {
            System.out.print(oo + " ");
        }
        System.out.println("");
    }

    public static void deb(long[] A) {

        for (Object oo : A) {
            System.out.print(oo + " ");
        }
        System.out.println("");
    }

    public static void deb(boolean[] A) {

        for (Object oo : A) {
            System.out.print(oo + " ");
        }
        System.out.println("");
    }

    public static void deb(double[] A) {

        for (Object oo : A) {
            System.out.print(oo + " ");
        }
        System.out.println("");
    }

    public static void deb(String[] A) {

        for (Object oo : A) {
            System.out.print(oo + " ");
        }
        System.out.println("");
    }

    public static void deb(int[][] A) {
        for (int i = 0; i < A.length; i++) {
            for (Object oo : A[i]) {
                System.out.print(oo + " ");
            }
            System.out.println("");
        }

    }

    public static void deb(double[][] A) {
        for (int i = 0; i < A.length; i++) {
            for (Object oo : A[i]) {
                System.out.print(oo + " ");
            }
            System.out.println("");
        }

    }

    public static void deb(long[][] A) {
        for (int i = 0; i < A.length; i++) {
            for (Object oo : A[i]) {
                System.out.print(oo + " ");
            }
            System.out.println("");
        }

    }

    public static void deb(String[][] A) {
        for (int i = 0; i < A.length; i++) {
            for (Object oo : A[i]) {
                System.out.print(oo + " ");
            }
            System.out.println("");
        }

    }
    /////////////////////////////////////////////////////////////

    int nextInt() throws IOException {
        in.nextToken();
        return (int) in.nval;
    }

    long nextLong() throws IOException {
        in.nextToken();
        return (long) in.nval;
    }

    void run() throws IOException {
//          in = new StreamTokenizer(new BufferedReader(new FileReader("input.txt")));
        // out = new PrintWriter(new FileWriter("output.txt"));
        in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(new OutputStreamWriter(System.out));
        solve();
        out.flush();
    }
//boolean inR(int x,int y){
//return (x<=0)&&(x<4)&&(y<=0)&&(y<4);
//}

    @SuppressWarnings("unchecked")
    void solve() throws IOException {
        //   BufferedReader re= new BufferedReader(new FileReader("C:\\Users\\ASELA\\Desktop\\PROBLEMSET\\input\\F\\10.in"));
   //           BufferedReader re = new BufferedReader(new InputStreamReader(System.in));
  //  Scanner sc= new Scanner(System.in);
 int N=nextInt();
 ArrayList<Integer> ts1=new ArrayList<Integer>();
  ArrayList<Integer> ts2=new ArrayList<Integer>();
  int tot=0,wid=0;
        for (int i = 0; i < N; i++) {
            if(nextInt()==1){
                int k=nextInt();
                tot+=k;
                ts1.add(k);}
            else {
                int k=nextInt();
                tot+=k;
                ts2.add(k);}
        }
        Collections.sort(ts2);
        Collections.sort(ts1);
  int[] one=new int[ts1.size()+1];
  int[] two=new int[ts2.size()+1];
  int l1=ts1.size(),l2=ts2.size();
  one[0]=0;
  two[0]=0;
        for (int i = 1; i <= l1; i++) {
            one[i]=one[i-1]+ts1.get(l1-i);
        }
         for (int i = 1; i <= l2; i++) {
            two[i]=two[i-1]+ts2.get(l2-i);
        }
         int minw=10000000;

        for (int i = 0; i <= l1; i++) {
            for (int j = 0; j < l2; j++) {
             if(tot-one[i]-two[j]<=i+2*j){
             if(i+2*j<minw)minw=i+2*j;
             }
            }
        }
        System.out.println(minw);
    }

}
class node{
int parent=-1;
    TreeSet<Integer> children= new TreeSet<Integer>();

}


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

public class Main{
    static FastReader in = new FastReader(new BufferedReader(new InputStreamReader(System.in)));
    static PrintWriter out = new PrintWriter(System.out);
    static final int maxn = (int)1e3 + 11;
    static int inf = (1<<30) - 1;
    static int n,m;
    static Pair a[] = new Pair[maxn];
    static ArrayList<Integer> one = new ArrayList<>();
    static ArrayList<Integer> two = new ArrayList<>();

    static int d[] = new int[maxn];
    static int dr[] = new int[maxn];

    public static void main(String[] args) throws Exception {

        n = in.nextInt();
        int sum = 0;
        for (int i=1; i<=n; i++) {
            int l = in.nextInt();
            int r = in.nextInt();
            a[i] = new Pair(l, r);
            sum+=l;
        }

        Arrays.sort(a,1,n+1);

        for (int i=1; i<=n; i++) {
            if (a[i].l==1) {
                one.add(a[i].r);
            }
            else {
                two.add(a[i].r);
            }
        }

        int w = 0;
        boolean ok = false;
        while (!one.isEmpty() && !two.isEmpty()) {
            if (ok) break;
//          out.println(one);
//          out.println(two);
//          out.println();
            if (one.size()>=2) {
                if (!two.isEmpty()) {
                    int l = one.get(0) + one.get(1);
                    int r = two.get(0);
                    if (l<=r) {
                        if (sum-2>=w+l) {
                            sum-=2;
                            w+=l;
                            one.remove(0);
                            one.remove(0);
                        } else {
                            if (sum-1>=w+one.get(0)) {
                                sum--;
                                w+=one.get(0);
                                one.remove(0);
                            } else {
                                break;
                            }
                        }
                    } else {
                        if (sum-2>=w+r) {
                            sum-=2;
                            w+=r;
                            two.remove(0);
                        } else {
                            if (sum-1>=w+one.get(0)) {
                                sum--;
                                w+=one.get(0);
                                one.remove(0);
                            } else {
                                break;
                            }
                        }
                    }
                } else {
                    if (sum-1>=w+one.get(0)) {
                        sum--;
                        w+=one.get(0);
                        one.remove(0);
                    } else {
                        break;
                    }
                }
            } else {
                if (!one.isEmpty()) {
                    int l = one.get(0);
                    if (!two.isEmpty()) {
                        int r = two.get(0);
                        if (l<=r) {
                            if (sum-1>=w+l) {
                                sum--;
                                w+=l;
                                one.remove(0);
                            } else {
                                break;
                            }
                        } else {
                            if (sum-2>=w+r) {
                                sum-=2;
                                w+=r;
                                two.remove(0);
                            } else {
                                break;
                            }
                        }
                    } else {
                        if (sum-1>=w+one.get(0)) {
                            sum--;
                            w+=one.get(0);
                            one.remove(0);
                        } else {
                            break;
                        }
                    }
                } else {
                    while (!two.isEmpty()) {
                        if (sum-2>=w+two.get(0)) {
                            sum-=2;
                            w+=two.get(0);
                            two.remove(0);
                        } else {
                            ok = true;
                            break;
                        }
                    }
                }
            }
        }

        out.println(sum);
        out.close();
    }

}

class Pair implements Comparable<Pair> {
    int l,r;
    public Pair (int l, int r) {
        this.l = l;
        this.r = r;
    }

    @Override
    public int compareTo(Pair p) {
        if (this.l<p.l) {
            return -1;
        } else if (this.l == p.l) {
            if (this.r<p.r) {
                return -1;
            } else if (this.r==p.r){
                return 0;
            } else {
                return 1;
            }
        } else {
            return 1;
        }
    }
}

class FastReader {

    BufferedReader bf;
    StringTokenizer tk = null;
    String DELIM = " ";

    public FastReader(BufferedReader bf) {
        this.bf = bf;
    }

    public String nextToken() throws Exception {

        if(tk==null || !tk.hasMoreTokens()) {
            tk = new StringTokenizer(bf.readLine(),DELIM);
        }
        return tk.nextToken();
    }

    public int nextInt() throws Exception {
        return Integer.parseInt(nextToken());
    }

    public long nextLong() throws Exception {
        return Long.parseLong(nextToken());
    }

    public double nextDouble() throws Exception {
        return Double.parseDouble(nextToken());
    }
}


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

public class Main{
    static FastReader in = new FastReader(new BufferedReader(new InputStreamReader(System.in)));
    static PrintWriter out = new PrintWriter(System.out);
    static final int maxn = (int)1e3 + 11;
    static int inf = (1<<30) - 1;
    static int n,m;
    static Pair a[] = new Pair[maxn];
    static ArrayList<Integer> one = new ArrayList<>();
    static ArrayList<Integer> two = new ArrayList<>();

    static int dl[] = new int[maxn];
    static int dr[] = new int[maxn];

    public static void main(String[] args) throws Exception {

        n = in.nextInt();
        int sum = 0;
        for (int i=1; i<=n; i++) {
            int l = in.nextInt();
            int r = in.nextInt();
            a[i] = new Pair(l, r);
            sum+=l;
        }

        Arrays.sort(a,1,n+1);

        for (int i=1; i<=n; i++) {
            if (a[i].l==1) {
                one.add(a[i].r);
                dl[one.size()]= dl[one.size()-1] + a[i].r;
            }
            else {
                two.add(a[i].r);
                dr[two.size()]= dr[two.size()-1] + a[i].r;
            }
        }

        int min = Integer.MAX_VALUE;
        for (int i=0; i<=one.size(); i++) {
            for (int j=0; j<=two.size(); j++) {
                if (sum-i-(2*j) >= dl[i]+dr[j]) {
                    min = Math.min(min,sum-i-(2*j));
                }
            }
        }

        out.println(min);
        out.close();
    }

}

class Pair implements Comparable<Pair> {
    int l,r;
    public Pair (int l, int r) {
        this.l = l;
        this.r = r;
    }

    @Override
    public int compareTo(Pair p) {
        if (this.l<p.l) {
            return -1;
        } else if (this.l == p.l) {
            if (this.r<p.r) {
                return -1;
            } else if (this.r==p.r){
                return 0;
            } else {
                return 1;
            }
        } else {
            return 1;
        }
    }
}

class FastReader {

    BufferedReader bf;
    StringTokenizer tk = null;
    String DELIM = " ";

    public FastReader(BufferedReader bf) {
        this.bf = bf;
    }

    public String nextToken() throws Exception {

        if(tk==null || !tk.hasMoreTokens()) {
            tk = new StringTokenizer(bf.readLine(),DELIM);
        }
        return tk.nextToken();
    }

    public int nextInt() throws Exception {
        return Integer.parseInt(nextToken());
    }

    public long nextLong() throws Exception {
        return Long.parseLong(nextToken());
    }

    public double nextDouble() throws Exception {
        return Double.parseDouble(nextToken());
    }
}


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

public class Main{
    static FastReader in = new FastReader(new BufferedReader(new InputStreamReader(System.in)));
    static PrintWriter out = new PrintWriter(System.out);
    static final int maxn = (int)1e3 + 11;
    static int inf = (1<<30) - 1;
    static int n,m;
    static Pair a[] = new Pair[maxn];
    static ArrayList<Integer> one = new ArrayList<>();
    static ArrayList<Integer> two = new ArrayList<>();

    static int d[] = new int[maxn];
    static int dr[] = new int[maxn];

    public static void main(String[] args) throws Exception {

        n = in.nextInt();
        int sum = 0;
        for (int i=1; i<=n; i++) {
            int l = in.nextInt();
            int r = in.nextInt();
            a[i] = new Pair(l, r);
            sum+=l;
        }

        Arrays.sort(a,1,n+1);

        for (int i=1; i<=n; i++) {
            if (a[i].l==1) {
                one.add(a[i].r);
            }
            else {
                two.add(a[i].r);
            }
        }

        int w = 0;
        boolean ok = false;
        while (!one.isEmpty() && !two.isEmpty()) {
            if (ok) break;
            out.println(one);
            out.println(two);
            out.println();
            if (one.size()>=2) {
                if (!two.isEmpty()) {
                    int l = one.get(0) + one.get(1);
                    int r = two.get(0);
                    if (l<=r) {
                        if (sum-2>=w+l) {
                            sum-=2;
                            w+=l;
                            one.remove(0);
                            one.remove(0);
                        } else {
                            if (sum-1>=w+one.get(0)) {
                                sum--;
                                w+=one.get(0);
                                one.remove(0);
                            } else {
                                break;
                            }
                        }
                    } else {
                        if (sum-2>=w+r) {
                            sum-=2;
                            w+=r;
                            two.remove(0);
                        } else {
                            if (sum-1>=w+one.get(0)) {
                                sum--;
                                w+=one.get(0);
                                one.remove(0);
                            } else {
                                break;
                            }
                        }
                    }
                } else {
                    if (sum-1>=w+one.get(0)) {
                        sum--;
                        w+=one.get(0);
                        one.remove(0);
                    } else {
                        break;
                    }
                }
            } else {
                if (!one.isEmpty()) {
                    int l = one.get(0);
                    if (!two.isEmpty()) {
                        int r = two.get(0);
                        if (l<=r) {
                            if (sum-1>=w+l) {
                                sum--;
                                w+=l;
                                one.remove(0);
                            } else {
                                break;
                            }
                        } else {
                            if (sum-2>=w+r) {
                                sum-=2;
                                w+=r;
                                two.remove(0);
                            } else {
                                break;
                            }
                        }
                    } else {
                        if (sum-1>=w+one.get(0)) {
                            sum--;
                            w+=one.get(0);
                            one.remove(0);
                        } else {
                            break;
                        }
                    }
                } else {
                    while (!two.isEmpty()) {
                        if (sum-2>=w+two.get(0)) {
                            sum-=2;
                            w+=two.get(0);
                            two.remove(0);
                        } else {
                            ok = true;
                            break;
                        }
                    }
                }
            }
        }

        out.println(sum);
        out.close();
    }

}

class Pair implements Comparable<Pair> {
    int l,r;
    public Pair (int l, int r) {
        this.l = l;
        this.r = r;
    }

    @Override
    public int compareTo(Pair p) {
        if (this.l<p.l) {
            return -1;
        } else if (this.l == p.l) {
            if (this.r<p.r) {
                return -1;
            } else if (this.r==p.r){
                return 0;
            } else {
                return 1;
            }
        } else {
            return 1;
        }
    }
}

class FastReader {

    BufferedReader bf;
    StringTokenizer tk = null;
    String DELIM = " ";

    public FastReader(BufferedReader bf) {
        this.bf = bf;
    }

    public String nextToken() throws Exception {

        if(tk==null || !tk.hasMoreTokens()) {
            tk = new StringTokenizer(bf.readLine(),DELIM);
        }
        return tk.nextToken();
    }

    public int nextInt() throws Exception {
        return Integer.parseInt(nextToken());
    }

    public long nextLong() throws Exception {
        return Long.parseLong(nextToken());
    }

    public double nextDouble() throws Exception {
        return Double.parseDouble(nextToken());
    }
}


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;

public class B {

	static StringTokenizer st;
	static BufferedReader in;
	public static void main(String[] args) throws IOException {
		in = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
		int n = nextInt();
		ArrayList<Integer> one = new ArrayList<Integer>(), two = new ArrayList<Integer>();
		int ans = 0;
		for (int i = 1; i <= n; i++) {
			int t = nextInt();
			int w = nextInt();
			if (t==1)
				one.add(w);
			else
				two.add(w);
			ans += t;
		}
		Collections.sort(one);
		Collections.sort(two);
		for (int i = 0; i <= one.size(); i++) {
			for (int j = 0; j <= two.size(); j++) {
				int think = (one.size()-i)+(two.size()-j)*2;
				int first = 0, second = 0;
				for (int k = 0; k < i; k++) {
					second += one.get(k);
				}
				for (int k = 0; k < j; k++) {
					second += two.get(k);
				}
				first = (one.size()-i)+(two.size()-j) * 2;
				if (first >= second)
					ans = Math.min(ans, think);
			}
		}
		System.out.println(ans);
		pw.close();
	}
	private static int nextInt() throws IOException{
		return Integer.parseInt(next());
	}

	private static long nextLong() throws IOException{
		return Long.parseLong(next());
	}

	private static double nextDouble() throws IOException{
		return Double.parseDouble(next());
	}

	private static String next() throws IOException {
        while (st == null || !st.hasMoreTokens()) {
            st = new StringTokenizer(in.readLine());
        }
        return st.nextToken();
    }
}


import java.io.*;
import java.util.*;
import java.math.*;
import java.awt.geom.*;

import static java.lang.Math.*;

public class Solution implements Runnable {

	public void solve() throws Throwable {
		int n = sc.nextInt();
		boolean can [][] = new boolean [2 * n + 1][2 * n + 1];
		boolean next [][] = new boolean [2 * n + 1][2 * n + 1];
		can[0][0] = true;
		for (int i = 0; i < n; i++) {
			int t = sc.nextInt();
			int w = sc.nextInt();
			for (int down = 0; down <= 2 * n; down++)
				for (int up = 0; up <= 2 * n; up++)
					if (can[down][up]) {
						// place down
						if (down + t <= 2 * n)
							next[down + t][up] = true;
						// place up
						if (up + w <= 2 * n)
							next[down][up + w] = true;
					}
			for (int down = 0; down <= 2 * n; down++)
				for (int up = 0; up <= 2 * n; up++) {
					can[down][up] = next[down][up];
					next[down][up] = false;
				}
		}
		int ans = Integer.MAX_VALUE / 2;
		for (int down = 0; down <= 2 * n; down++)
			for (int up = 0; up <= 2 * n; up++) {
				if (down >= up && can[down][up])
					ans = min (ans, down);
			}
		out.println(ans);
	}

	BufferedReader in;
	PrintWriter out;
	FastScanner sc;

	static Throwable uncaught;

	@Override
	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			sc = new FastScanner(in);
			solve();
		} catch (Throwable t) {
			Solution.uncaught = t;
		} finally {
			out.close();
		}
	}

	public static void main(String[] args) throws Throwable {
		Thread t = new Thread(null, new Solution(), "", (1 << 26));
		t.start();
		t.join();
		if (uncaught != null) {
			throw uncaught;
		}
	}

}

class FastScanner {

	BufferedReader reader;
	StringTokenizer strTok;

	public FastScanner(BufferedReader reader) {
		this.reader = reader;
	}

	public String nextToken() throws IOException {
		while (strTok == null || !strTok.hasMoreTokens()) {
			strTok = new StringTokenizer(reader.readLine().trim());
		}
		return strTok.nextToken();
	}

	public int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	public long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	public double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}

}


import java.util.*;

public class B {
  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int books = in.nextInt();
    // for each possible 'total thickness' find the maximum width.
    int totalWidth = 0;
    int[] maxWidth = new int[books*2+1];
    Arrays.fill(maxWidth, -1);
    maxWidth[0] = 0;
    for (int i = 0; i < books; ++i) {
      int thickness = in.nextInt();
      int width = in.nextInt();
      for (int curT = maxWidth.length - thickness; curT >= 0; --curT) {
        if (maxWidth[curT] != -1) {
          int attempt = maxWidth[curT] + width;
          if (attempt > maxWidth[curT+thickness]) {
            maxWidth[curT+thickness] = attempt;
          }
        }
      }
      totalWidth += width;
    }
    // now, iterate through the maxWidth array, find smallest
    // thickness T such that totalWidth - maxWidth[T] <= T
    int ans = -1;
    for (int bestThick = 0; bestThick < maxWidth.length; ++bestThick) {
      if (maxWidth[bestThick] == -1)
        continue;
      if (totalWidth - maxWidth[bestThick] <= bestThick) {
        ans = bestThick;
        break;
      }
    }
    System.out.println(ans);
  }
}


import java.io.*;
import java.util.*;
public class j
{
public static void main(String aa[])throws IOException
{
BufferedReader b=new BufferedReader(new InputStreamReader(System.in));
int p1=0,t1=0,min=100000000,i=0,t=0,u=0,v=0,p=0,m=0,l=0,k=0;
String s;
m=Integer.parseInt(b.readLine());
int d[]=new int[m];
int e[]=new int[m];
for(i=0;i<m;i++)
{
s=b.readLine();
StringTokenizer y=new StringTokenizer(s);
d[i]=Integer.parseInt(y.nextToken());
e[i]=Integer.parseInt(y.nextToken());
l+=e[i];
if(d[i]==1)
p++;
}
int f[]=new int[p+1];
int g[]=new int[p+1];
int h[]=new int[m-p+1];
int j[]=new int[m-p+1];
for(i=0;i<m;i++)
{
if(d[i]==1)
{
f[k]=d[i];
g[k]=e[i];
k++;
}
if(d[i]==2)
{
h[t]=d[i];
j[t]=e[i];
t++;
}
}
f[p]=0;
g[p]=0;
h[m-p]=0;
j[m-p]=0;
for(i=0;i<p;i++)
{
for(k=i+1;k<p+1;k++)
{
if(g[k]<g[i])
{
t=g[k];
g[k]=g[i];
g[i]=t;
}
}
}
for(i=0;i<m-p;i++)
{
for(k=i+1;k<m-p+1;k++)
{
if(j[k]<j[i])
{
t=j[k];
j[k]=j[i];
j[i]=t;
}
}
}
p1=0;
t1=0;
u=0;
v=0;
for(i=0;i<p+1;i++)
{
p1+=f[i];
u+=g[i];
for(k=0;k<m-p+1;k++)
{
t1+=h[k];
v+=j[k];
if(l-v-u<=p1+t1)
break;
}
if(p1+t1<min&&p1+t1!=0)
min=p1+t1;
t1=0;
v=0;
}
System.out.print(min);
}
}


import java.io.*;
import java.util.*;
public class j
{
public static void main(String aa[])throws IOException
{
BufferedReader b=new BufferedReader(new InputStreamReader(System.in));
int p1=0,x=0,t1=0,min=100000000,i=0,t=0,u=0,v=0,p=0,m=0,l=0,k=0;
String s;
m=Integer.parseInt(b.readLine());
int d[]=new int[m];
int e[]=new int[m];
for(i=0;i<m;i++)
{
s=b.readLine();
StringTokenizer y=new StringTokenizer(s);
d[i]=Integer.parseInt(y.nextToken());
e[i]=Integer.parseInt(y.nextToken());
l+=e[i];
if(d[i]==1)
p++;
}
int f[]=new int[p+1];
int g[]=new int[p+1];
int h[]=new int[m-p+1];
int j[]=new int[m-p+1];
for(i=0;i<m;i++)
{
if(d[i]==1)
{
f[k]=d[i];
g[k]=e[i];
k++;
}
if(d[i]==2)
{
h[t]=d[i];
j[t]=e[i];
t++;
}
}
f[p]=0;
g[p]=0;
h[m-p]=0;
j[m-p]=0;
for(i=0;i<p;i++)
{
for(k=i+1;k<p+1;k++)
{
if(g[k]>g[i])
{
t=g[k];
g[k]=g[i];
g[i]=t;
}
}
}
for(i=0;i<m-p;i++)
{
for(k=i+1;k<m-p+1;k++)
{
if(j[k]>j[i])
{
t=j[k];
j[k]=j[i];
j[i]=t;
}
}
}
p1=0;
t1=0;
u=0;
v=0;
for(i=0;i<p+1;i++)
{
p1+=f[i];
u+=g[i];
for(k=0;k<m-p+1;k++)
{
t1+=h[k];
v+=j[k];
if(l-v-u<=p1+t1)
{x=1;break;}
}
if(p1+t1<min&&p1+t1!=0&&x==1)
min=p1+t1;
t1=0;
v=0;
x=0;
}
System.out.print(min);
}
}


import java.io.*;
import java.util.*;
public class j
{
public static void main(String aa[])throws IOException
{
BufferedReader b=new BufferedReader(new InputStreamReader(System.in));
int p1=0,x=0,t1=0,min=100000000,min1=100000000,i=0,t=0,u=0,v=0,p=0,m=0,l=0,k=0;
String s;
m=Integer.parseInt(b.readLine());
int d[]=new int[m];
int e[]=new int[m];
for(i=0;i<m;i++)
{
s=b.readLine();
StringTokenizer y=new StringTokenizer(s);
d[i]=Integer.parseInt(y.nextToken());
e[i]=Integer.parseInt(y.nextToken());
l+=e[i];
if(d[i]==1)
p++;
}
int f[]=new int[p+1];
int g[]=new int[p+1];
int h[]=new int[m-p+1];
int j[]=new int[m-p+1];
for(i=0;i<m;i++)
{
if(d[i]==1)
{
f[k]=d[i];
g[k]=e[i];
k++;
}
if(d[i]==2)
{
h[t]=d[i];
j[t]=e[i];
t++;
}
}
f[p]=0;
g[p]=0;
h[m-p]=0;
j[m-p]=0;
for(i=0;i<p;i++)
{
for(k=i+1;k<p+1;k++)
{
if(g[k]>g[i])
{
t=g[k];
g[k]=g[i];
g[i]=t;
}
}
}
for(i=0;i<m-p;i++)
{
for(k=i+1;k<m-p+1;k++)
{
if(j[k]>j[i])
{
t=j[k];
j[k]=j[i];
j[i]=t;
}
}
}
p1=0;
t1=0;
u=0;
v=0;
for(i=0;i<p+1;i++)
{
p1+=f[i];
u+=g[i];
for(k=0;k<m-p+1;k++)
{
t1+=h[k];
v+=j[k];
if(l-v-u<=p1+t1)
{x=1;break;}
}
if(p1+t1<min&&p1+t1!=0&&x==1)
min=p1+t1;
t1=0;
v=0;
x=0;
}
p1=0;
t1=0;
u=0;
v=0;
x=0;
for(i=p;i>=0;i--)
{
p1+=f[i];
u+=g[i];
for(k=m-p;k>=0;k--)
{
t1+=h[k];
v+=j[k];
if(l-v-u<=p1+t1)
{x=1;break;}
}
if(p1+t1<min1&&p1+t1!=0&&x==1)
min1=p1+t1;
t1=0;
v=0;
x=0;
}
System.out.print((long)Math.min(min,min1));
}
}


import java.io.*;
import java.util.*;
public class j
{
public static void main(String aa[])throws IOException
{
BufferedReader b=new BufferedReader(new InputStreamReader(System.in));
int i=0,t=0,p=0,m=0,j=0,k=0;
String s;
m=Integer.parseInt(b.readLine());
int d[]=new int[m];
int e[]=new int[m];
for(i=0;i<m;i++)
{
s=b.readLine();
StringTokenizer y=new StringTokenizer(s);
d[i]=Integer.parseInt(y.nextToken());
e[i]=Integer.parseInt(y.nextToken());
p+=e[i];
}
for(i=0;i<m-1;i++)
{
for(j=i+1;j<m;j++)
{
if(e[j]>e[i])
{
t=e[j];
e[j]=e[i];
e[i]=t;
t=d[j];
d[j]=d[i];
d[i]=t;
}
}
}
for(i=0;i<m;i++)
{
k+=d[i];
p-=e[i];
if(p<=k)
break;
}
System.out.print(k);
}
}


import java.io.*;
import java.util.*;
public class j
{
public static void main(String aa[])throws IOException
{
BufferedReader b=new BufferedReader(new InputStreamReader(System.in));
int p1=0,t1=0,min=100000000,i=0,t=0,u=0,v=0,p=0,m=0,l=0,k=0;
String s;
m=Integer.parseInt(b.readLine());
int d[]=new int[m];
int e[]=new int[m];
for(i=0;i<m;i++)
{
s=b.readLine();
StringTokenizer y=new StringTokenizer(s);
d[i]=Integer.parseInt(y.nextToken());
e[i]=Integer.parseInt(y.nextToken());
l+=e[i];
if(d[i]==1)
p++;
}
int f[]=new int[p+1];
int g[]=new int[p+1];
int h[]=new int[m-p+1];
int j[]=new int[m-p+1];
for(i=0;i<m;i++)
{
if(d[i]==1)
{
f[k]=d[i];
g[k]=e[i];
k++;
}
if(d[i]==2)
{
h[t]=d[i];
j[t]=e[i];
t++;
}
}
f[p]=0;
g[p]=0;
h[m-p]=0;
j[m-p]=0;
for(i=0;i<p;i++)
{
for(k=i+1;k<p+1;k++)
{
if(g[k]>g[i])
{
t=g[k];
g[k]=g[i];
g[i]=t;
}
}
}
for(i=0;i<m-p;i++)
{
for(k=i+1;k<m-p+1;k++)
{
if(j[k]>j[i])
{
t=j[k];
j[k]=j[i];
j[i]=t;
}
}
}
p1=0;
t1=0;
u=0;
v=0;
for(i=0;i<p+1;i++)
{
p1+=f[i];
u+=g[i];
for(k=0;k<m-p+1;k++)
{
t1+=h[k];
v+=j[k];
if(l-v-u<=p1+t1)
break;
}
if(p1+t1<min&&p1+t1!=0)
min=p1+t1;
t1=0;
v=0;
}
System.out.print(min);
}
}


import java.io.*;
import java.util.*;
public class j
{
public static void main(String aa[])throws IOException
{
BufferedReader b=new BufferedReader(new InputStreamReader(System.in));
int min=100000000,i=0,t=0,u=0,v=0,p=0,m=0,l=0,k=0;
String s;
m=Integer.parseInt(b.readLine());
int d[]=new int[m];
int e[]=new int[m];
for(i=0;i<m;i++)
{
s=b.readLine();
StringTokenizer y=new StringTokenizer(s);
d[i]=Integer.parseInt(y.nextToken());
e[i]=Integer.parseInt(y.nextToken());
l+=e[i];
if(d[i]==1)
p++;
}
int f[]=new int[p+1];
int g[]=new int[p+1];
int h[]=new int[m-p+1];
int j[]=new int[m-p+1];
for(i=0;i<m;i++)
{
if(d[i]==1)
{
f[k]=d[i];
g[k]=e[i];
k++;
}
if(d[i]==2)
{
h[t]=d[i];
j[t]=e[i];
t++;
}
}
f[p]=0;
g[p]=0;
h[m-p]=0;
j[m-p]=0;
for(i=0;i<p;i++)
{
for(k=i+1;k<p+1;k++)
{
if(g[k]>g[i])
{
t=g[k];
g[k]=g[i];
g[i]=t;
t=f[k];
f[k]=f[i];
f[i]=t;
}
}
}
for(i=0;i<m-p;i++)
{
for(k=i+1;k<m-p+1;k++)
{
if(j[k]>j[i])
{
t=j[k];
j[k]=j[i];
j[i]=t;
t=h[k];
h[k]=h[i];
h[i]=t;
}
}
}
p=0;
t=0;
u=0;
v=0;
for(i=0;i<p+1;i++)
{
p+=f[i];
u+=g[i];
for(k=0;k<m-p+1;k++)
{
t+=h[k];
v+=j[k];
if(l-v-u<=p+t)
break;
}
if(p+t<min&&p+t!=0)
min=p+t;
t=0;
v=0;
}
System.out.print(min);
}
}


import java.util.Scanner;
import java.util.TreeSet;

/**
 *
 * @author Do Quoc bao
 */
public class ProblemB {
    public static void main(String[] args) {
	Scanner in=new Scanner(System.in);
	int n=in.nextInt();
	int totalThick=0;
	int kq=Integer.MAX_VALUE;
	int[] t=new int[n],w=new int[n];
	for (int i=0;i<n;++i) {
	    t[i]=in.nextInt();totalThick+=t[i];
	    w[i]=in.nextInt();
	}
	TreeSet<config> set=new TreeSet<>();
	set.add(new config(0,totalThick,new TreeSet<Integer>()));
	while (!set.isEmpty()) {
	    config C=set.pollFirst();
	    int thk=C.thick;kq=Math.min(kq, thk);
	    int wid=C.sum;
	    for (int i=0;i<n;++i) if (!C.above.contains(i)) {
		if ((thk-t[i])>=(wid+w[i])) {
		    TreeSet<Integer> newSet=new TreeSet<>(C.above);
		    newSet.add(i);
		    set.add(new config(wid+w[i],thk-t[i],newSet));
		}
	    }
	}
	System.out.println(kq);
    }
}

class config implements Comparable {
    int sum,thick;
    TreeSet<Integer> above;
    public config(int newSum,int newThick,TreeSet<Integer> newAbove) {
	sum=newSum;thick=newThick;above=new TreeSet<>(newAbove);
    }
    @Override
    public int compareTo(Object o) {
	config other=(config)o;
	if (this.sum<other.sum) return -1;
	else if (this.sum==other.sum) {
	    return Integer.compare(this.thick, other.thick);
	}
	else return 1;
    }
}


import java.util.*;

public class ShaassAndBookshelf {
  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int n = in.nextInt();
    int[] t = new int[n];
    int[] w = new int[n];
    int maxW = 0;
    for (int i = 0; i < n; i++) {
      t[i] = in.nextInt();
      w[i] = in.nextInt();
      maxW += t[i];
    }
    int dp[] = new int[maxW + 1];
    dp[0] = 0;
    for (int j = 1; j < maxW + 1; j++) {
      dp[j] = 999999;
    }
    for (int i = 0; i < n; i++) {
      for (int j = maxW; j >= 0; j--) {
        if (j < t[i] ) {
          dp[j] += w[i];
        } else {
          dp[j] = Math.min(dp[j] + w[i], dp[j - t[i]]);
        }
      }
    }
    for (int j = 0; j <= maxW; j++) {
      if (dp[j] <= j) {
       System.out.println(j);
       break;
      }
    }
    in.close();
  }
}


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

public class B294 implements Runnable {

	public void solve() throws IOException {
		int N = nextInt();
                ArrayList<Integer> one = new ArrayList<>();
                ArrayList<Integer> two = new ArrayList<>();
                for(int i = 0; i < N; i++){
                    int type = nextInt();
                    int widht = nextInt();
                    if(type == 2) two.add(widht);
                    else one.add(widht);
                }

                Collections.sort(one);
                Collections.sort(two);

                int answer = Integer.MAX_VALUE;
                for(int i = 0; i <= one.size(); i++)
                    for(int j = 0; j <= two.size(); j++){
                        int placeUp = 0;
                        for(int k = 0; k < i; k++) placeUp += one.get(k);
                        for(int k = 0; k < j; k++) placeUp += two.get(k);

                        int placeDown = (one.size() - i) + (two.size() - j) * 2;
                        if(placeDown >= placeUp){
                            answer = Math.min(answer, placeDown);
                        }
                    }

                out.println(answer);
	}

	//-----------------------------------------------------------
	public static void main(String[] args) {
		new B294().run();
	}

        public void debug(Object... arr){
            System.out.println(Arrays.deepToString(arr));
        }

        public void print1Int(int[] a){
                for(int i = 0; i < a.length; i++)
                        System.out.print(a[i] + " ");
                System.out.println();
        }

        public void print2Int(int[][] a){
                for(int i = 0; i < a.length; i++){
                        for(int j = 0; j < a[0].length; j++){
                                System.out.print(a[i][j] + " ");
                        }
                        System.out.println();
                }
        }

	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
                        out = new PrintWriter(System.out);
			tok = null;
			solve();
			in.close();
                        out.close();
		} catch (IOException e) {
			System.exit(0);
		}
	}

	public String nextToken() throws IOException {
		while (tok == null || !tok.hasMoreTokens()) {
			tok = new StringTokenizer(in.readLine());
		}
		return tok.nextToken();
	}

	public int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	public long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	public double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}
        PrintWriter out;
	BufferedReader in;
	StringTokenizer tok;
}


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

public class B294 implements Runnable {
		class Book implements Comparable<Book>{
                        int t;
                        int w;
                        Book(int tt, int ww){
                                t = tt;
                                w = ww;
                        }

                        public int compareTo(Book b){
                                if(w != b.w) return -(w - b.w);
                                return -(t - b.t);
                        }
                }

                Book[] books;
                int N;
                int res = Integer.MAX_VALUE;

        private void doit(int index, int totalThickness, int thicknessLeft){
                if(index == N){
                        res = Math.min(totalThickness, res);
                        return ;
                }

                //add to the side
                doit(index + 1, totalThickness + books[index].t, thicknessLeft + books[index].t);
                //add to the top
                if(thicknessLeft >= books[index].w){
                        doit(index + 1, totalThickness, thicknessLeft - books[index].w);
                }
        }

        public void solve() throws IOException {
		N = nextInt();
                books = new Book[N];
                for(int i = 0; i < N; i++) books[i] = new Book(nextInt(), nextInt());
                Arrays.sort(books);

                doit(0, 0, 0); //index, totalThickness, thicknessleft

                System.out.println(res);
	}

	//-----------------------------------------------------------
	public static void main(String[] args) {
		new B294().run();
	}

	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			tok = null;
			solve();
			in.close();
		} catch (IOException e) {
			System.exit(0);
		}
	}

	public String nextToken() throws IOException {
		while (tok == null || !tok.hasMoreTokens()) {
			tok = new StringTokenizer(in.readLine());
		}
		return tok.nextToken();
	}

	public int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	public long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	public double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}

	BufferedReader in;
	StringTokenizer tok;
}