Problem:
ランチ

お昼に食べるお弁当を作るために、お店で食べ物を買いました。お店では、食べ物を入れるのに細長い袋しかもらえなかったので、すべての食べ物を縦に積んで袋に入れる必要があります。袋が倒れにくいように、できるだけ重い物を下にして詰めたいのですが、食べ物の中にはやわらかい物もあって、上に重い物を乗せるとつぶれてしまいます。

そこで、食べ物の情報を入力とし、全ての食べ物がつぶれず、かつ全体の重心が最も低くなるような積み方を出力するプログラムを作成してください。それぞれの食べ物ごとに、名前 f、重さ w、上に載せて耐えられる重さ s が指定されます。
「全ての食べ物がつぶれない」というのは、下から順に、（f1、f2、... 、fn）と n 個の食べ物を積んだ時、すべての f について、

sfi ≥ wfi+1 + wfi+2 + ... + wfn

であることを意味します。また、全体の重心 G は、

G = (1 × wf1 + 2 × wf2 + ... + n × wfn) / (wf1 + wf2+ ... +wfn)

とします。ただし、解はちょうど1つだけ存在するものとします。

Input

複数のデータセットの並びが入力として与えられます。入力の終わりはゼロひとつの行で示されます。各データセットは以下の形式で与えられます。

n
f1 w1 s1
f2 w2 s2
:
fn wn sn

１行目に食べ物の個数 n (1 ≤ n ≤ 10)、続く n 行に i 番目の食べ物の名前 fi (20 文字以内の半角英文字列)、重さ wi (1 ≤ wi ≤ 1000)、耐えられる重さ si (1 ≤ si ≤ 1000) が空白区切りで与えられます。

データセットの数は 20 を超えません。

Output

データセットごとに、次の形式で食べ物の名前を下から積み上げる順に出力します。

1 行目: 1 番下の食べ物の名前（半角英文字列）

2 行目: 下から2 番目の食べ物の名前

：

n 行目: 1 番上の食べ物の名前

Sample Input

4
sandwich 80 120
apple 50 200
cheese 20 40
cake 100 100
9
onigiri 80 300
onigiri 80 300
anpan 70 280
mikan 50 80
kanzume 100 500
chocolate 50 350
cookie 30 80
purin 40 400
cracker 40 160
0

Output for the Sample Input

apple
cake
sandwich
cheese
kanzume
purin
chocolate
onigiri
onigiri
anpan
mikan
cracker
cookie

Solution in JAVA (judge verdict: Accepted)

import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

	public static final int BIG_NUM = 2000000000;
	public static final int MOD = 1000000007;
	public static final long HUGE_NUM = 99999999999999999L;
	public static final double EPS = 0.000000001;


	public static double value;
	public static int N;
	public static final int SIZE = 10;
	public static Info info[];
	public static int table[];
	public static boolean used[];
	public static int ANS[];

	@SuppressWarnings("unchecked")
	public static void main(String[] args) {

		//BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		Scanner scanner = new Scanner(System.in);

		info = new Info[SIZE];
		table = new int[SIZE];
		used = new boolean[SIZE];
		ANS = new int[SIZE];

		for(int i = 0; i < SIZE; i++){

			info[i] = new Info();
		}

		StringBuffer ans = new StringBuffer();

		while(true){

			N = scanner.nextInt();
			if(N == 0)break;

			double total_weight = 0;

			for(int i = 0; i < N; i++){

				info[i].set(scanner.next(), scanner.nextInt(), scanner.nextInt());
				total_weight += info[i].weight;
			}

			value = (double)HUGE_NUM;

			for(int i = 0; i < N; i++){
				if(total_weight-info[i].weight > info[i].can_stand)continue;

				table[0] = i;
				used[i] = true;
				recursive(1);
				used[i] = false;
			}

			for(int i = 0; i < N; i++){

				ans.append(info[ANS[i]].name).append("\n");
			}
		}

		System.out.print(ans.toString());
	}

	public static void recursive(int index){

		if(index == N){

			double numerator = 0,denominator = 0;
			for(int i = 1; i <= N; i++){

				numerator += (double)i*info[table[i-1]].weight;
			}
			for(int i = 0; i < N; i++){

				denominator += info[table[i]].weight;
			}

			double tmp = numerator/denominator;

			if(value > tmp){
				value = tmp;

				for(int i = 0; i < N; i++){

					ANS[i] = table[i];
				}
			}

			return;
		}

		//残っている人の体重の和
		double rest_weight = 0;
		for(int i = 0; i < N; i++){
			if(used[i])continue;

			rest_weight += info[i].weight;
		}

		for(int i = 0; i < N; i++){
			if(used[i])continue;
			if(rest_weight-info[i].weight > info[i].can_stand)continue;

			table[index] = i;
			used[i] = true;
			recursive(index+1);
			used[i] = false;
		}
	}
}

class Info{

	public String name;
	public int weight;
	public int can_stand;

	void set(String arg_name,int arg_weight,int arg_can_stand){
		name = arg_name;
		weight = arg_weight;
		can_stand = arg_can_stand;
	}
}

class UTIL{

	//最大公約数
	public static long gcd(long x,long y){

		x = Math.abs(x);
		y = Math.abs(y);

		if(x < y){

			long tmp = y;
			y = x;
			x = tmp;
		}

		if(y == 0){

			return x;
		}else{

			return gcd(y,x%y);
		}
	}

	//最小公倍数
	public static long lcm(long x,long y){

		return (x*y)/gcd(x,y);
	}

	//String→intへ変換
    public static int getNUM(String tmp_str){

        return Integer.parseInt(tmp_str);
    }

    //文字が半角数字か判定する関数
    public static boolean isNumber(String tmp_str){

        if(tmp_str == null || tmp_str.length() == 0){

            return false;
        }

        Pattern pattern = Pattern.compile("\\A[0-9]+\\z");
        Matcher matcher = pattern.matcher(tmp_str);
        return matcher.matches();
    }
}