Problem:
力持ち

力持ちたちが集う力持ち学園がありました。力持ち学園の運動会では、力持ちたちが隊列を組んで行進します。

力持ちたちは常に自分たちの力を誇示したい一方で、彼らの大半は自分で歩きたくありません。そこで彼らの一部が一番下になり、その上に大勢の人を縦一列に持ちあげて歩くことで、実際に歩く人数を減らそうと考えました。

はじめに、N 人の力持ちは地面の上に横一列に並んでいて、それぞれ左側から １,２,３,..., N と通し番号で呼ばれています。通し番号 i の力持ちの体重は wi で最大 ci の重量まで持つことができます。

力持ちは、以下の条件をすべて満たすときだけ、隣に立っている左右どちらかの力持ちを持ちあげることができます。

自分の上下には力持ちはいない。つまり、誰かに持ち上げられてもいないし、誰かを持ちあげてもいない。

隣の力持ちの体重が、自分が持つことのできる最大の重量以下である。ただし、隣の力持ちが既に誰かを持ち上げているなら、縦に積み上がった力持ちたちの体重の合計が、自分が持つことのできる最大の重量以下でなければならない。

例えば、次のような３人の力持ちの隊列を考えてみましょう。

下図のように、２の力持ちが持つことのできる重さが w3 以上のとき、２の力持ちは３の力持ちを持ちあげることができます。続いて、１の力持ちが持つことのできる重さが w2 + w3 以上のとき、１の力持ちは２の力持ちを持ちあげることができます。

       
→
       

また、下図のように３の力持ちが２の力持ちを持ちあげた場合は、１の力持ちの隣が、２の力持ちを持った３の力持ちになるので、１の力持ちは３の力持ちを持ちあげることができます。

       
→
       

２の力持ちが、下の図のように１と３の力持ちを両方持つことはできません。

力持ち学園の専属プログラマーとして、一番下で歩くことになる最小の人数を求めてください。

入力

入力は以下の形式で与えられる。

N
c1 w1
c2 w2
:
cN wN

1 行目に力持ちの人数 N (1 ≤ N ≤ 1000) が与えられる。続く N 行に i 番目の力持ちが持てる重量の最大値 ci (1 ≤ ci ≤ 100000) と体重 wi (1 ≤ wi ≤ 100000) が与えられる。

出力

最小の人数を１行に出力する。

入出力例

入力例１

3
150 120
100 50
80 100

出力例１

1

入力例２

8
50 100
20 20
30 20
90 50
140 30
30 60
59 120
10 10

出力例２

3

Solution in JAVA (judge verdict: Wrong Answer)

import java.io.*;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Mighty Man (http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0303)
 * 
 * @author ikaruga
 */
class Main {
	
	static Comparator<MightyMan> compareMaxLiftWeightAsc = (a, b) -> a.getMaxLiftWeight() - b.getMaxLiftWeight();
	static Comparator<MightyMan> compareBodyWeightAsc = (a, b) -> a.getBodyWeight() - b.getBodyWeight();
	
	public static void main(String[] args) {
		// long systemTime = System.currentTimeMillis();
		// System.out.println("- start -");

		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(
					System.in));
			List<MightyMan> manList = br.lines().skip(1)
					.map(l -> new MightyMan(l.split("\\s")))
					.collect(Collectors.toList());

			// ????°????????????°?????????
			int resultCnt = getMinimumNumberOfMan(manList);

			// ????????????
			System.out.println(resultCnt);

		} catch (Exception e) {
			e.printStackTrace();
		}
		// System.out.println("- end - "
		// + String.valueOf(System.currentTimeMillis() - systemTime)
		// + "ms");
	}

	/**
	 * ????????????????°????????????°????±???????
	 * 
	 * @param manList
	 * @return
	 */
	private static int getMinimumNumberOfMan(List<MightyMan> manList) {
		boolean canLift = false;
		do {
			// debug
//			System.out.println("### start output ###");
//			manList.stream().forEach(System.out::println);

			int size = manList.size();
			// 1???????????£????????????
			if (size == 1)
				break;

			// ??°??????????????????????????????????????????
			MightyMan minWeightMan = manList.stream()
					.filter(man -> man.isLift() && !man.isFixed)
					.findFirst().orElse(null);
			canLift = liftMan(manList, minWeightMan);
			if (canLift)
				continue;

			// ??°??????????????????????????????????????????
			minWeightMan = manList
					.stream()
					.filter(man -> !man.isLift())
					.sorted(compareMaxLiftWeightAsc)
					.min(compareBodyWeightAsc)
					.orElse(null);
			canLift = liftMan(manList, minWeightMan);

		} while (canLift);

		return manList.size();
	}

	/**
	 * ?????????????°????????????£??????????????????????????????????????????????????????????????????????????????</br> ??????????????????????????????????????´???????????????????????????
	 * 
	 * @param manList
	 * @param minWeightMan
	 * @return true : ???????????????????????´???</br> false : ??????????????????????????£?????´???
	 */
	public static boolean liftMan(List<MightyMan> manList,
			MightyMan minWeightMan) {

		if (minWeightMan != null) {
			int minWeightManIdx = manList.indexOf(minWeightMan);
			MightyMan targetMan;
			if (minWeightManIdx == 0) {
				targetMan = manList.get(minWeightManIdx + 1);
			} else if (minWeightManIdx == manList.size() - 1) {
				targetMan = manList.get(minWeightManIdx - 1);
			} else {
				targetMan = Stream
						.of(manList.get(minWeightManIdx - 1),
								manList.get(minWeightManIdx + 1))
						.filter(man -> !man.isLift() && man.canLift(minWeightMan))
						.sorted(compareBodyWeightAsc)
						.min(compareMaxLiftWeightAsc).orElse(null);
			}

			// ??????????????????fix??????
			minWeightMan.setFixed();
			if (targetMan == null)
				return false;
			if (targetMan.tryLift(minWeightMan)) {
				manList.remove(minWeightMan);
				return true;
			}
		}
		return false;
	}

	/**
	 * ?????????
	 * 
	 * @author ikaruga
	 *
	 */
	static class MightyMan {
		private int bodyWeight = 0;
		private int maxLiftWeight = 0;

		// ????????????????????????
		private MightyMan aboveMan = null;

		// ?¢??????¶???(??????????????????????????????????????£??????????????¶??? or ?????????????????????????????¶???)
		private boolean isFixed = false;

		public MightyMan(String[] manSpec) {
			this.maxLiftWeight = Integer.parseInt(manSpec[0]);
			this.bodyWeight = Integer.parseInt(manSpec[1]);
		}

		public boolean tryLift(MightyMan man) {
			if (!isLift() && canLift(man)) {
				this.aboveMan = man;
				return true;
			}
			return false;
		}

		public boolean isLift() {
			return aboveMan != null;
		}

		public boolean canLift(MightyMan man) {
			return maxLiftWeight >= man.getBodyWeight();
		}

		public int getBodyWeight() {
			return aboveMan == null ? bodyWeight : bodyWeight
					+ aboveMan.getBodyWeight();
		}

		public int getMaxLiftWeight() {
			return aboveMan == null ? maxLiftWeight : maxLiftWeight
					- aboveMan.getBodyWeight();
		}

		public boolean isFixed() {
			return isFixed;
		}

		public void setFixed() {
			this.isFixed = true;
		}

		@Override
		public String toString() {
			return "MightyMan [bodyWeight=" + bodyWeight + ", maxLiftWeight="
					+ maxLiftWeight + ", isFixed=" + isFixed
					+ ", getBodyWeight()=" + getBodyWeight()
					+ ", getMaxLiftWeight()=" + getMaxLiftWeight()
					+ ", aboveMan=" + aboveMan + "]";
		}

	}
}