Problem:
Problem A: Rental DVD Shop NEO

Problem

僕はレンタルDVDショップ、「NEO」でアルバイトを始めた。まずはこの店の料金システムを勉強することになった。

レンタルDVDは旧作、準新作、新作の3種類存在し、1本のレンタル料金がそれぞれ a 円、 b 円、 c 円である。
会計の際に以下に示すセットレンタルを複数回適用することができる。

まだセットレンタルを適用していないDVDを数本選ぶ。

選んだDVDの本数が d 本以上の場合、選んだDVDの合計金額が、 (選んだDVDの本数) * e 円を超える場合は、それらを (選んだDVDの本数) * e 円でレンタル出来る。

選んだDVDの本数が d 本未満の場合、選んだDVDの合計金額が d * e 円を超える場合は、それらを d * e 円でレンタル出来る。

上記に当てはまらない場合、選んだDVDは通常料金でレンタルとなる。

ここで僕はある問題に気づいた。セットレンタルはレジに通した時に自動的に適用されるのではなく、手動で適用しているのだ。これでは最適ではない（もっと安くなる余地がある）セットレンタルの適用をしてしまう可能性がある。これではクレームが発生しかねない。僕はクレーム対応が嫌いなので、セットレンタルを最適に適用した時の料金を計算するプログラムを作成することにした。

Input

入力は複数のデータセットからなる。
各データセットは以下で表される。
1行目は5つの整数 a , b , c , d , e がスペース区切りで与えられる。
2行目にはレンタル本数が与えられる。3つの整数 na , nb , nc がスペース区切りで与えられる。それぞれ旧作、準新作、新作のDVDの本数を表す。
入力の終わりは5つのゼロからなる。

a b c d e
na nb nc

Constraints

入力は以下の条件を満たす。

入力に含まれる値はすべて整数

0 < a < b < e < c ≤ 1000

0 < d ≤ 100000

0 ≤ na , nb , nc ≤ 100000

0 < na + nb + nc

データセットの数は100個以下

Output

各データセットにつき、セットレンタルを最適に適用した時の料金を1行に出力せよ。

Sample Input

70 100 340 4 200
1 1 4
70 100 340 4 200
0 1 3
70 100 340 4 200
1 1 2
0 0 0 0 0

Sample Output

970
800
800

Solution in JAVA (judge verdict: Runtime Error)



import java.util.ArrayList;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);

		// 出力用変数を用意
		StringBuilder out = new StringBuilder();

		// 入力値がある限りまわす
		while (sc.hasNext()) {

			/**
			 * すべてのビデオを入れるリスト
			 */
			ArrayList<Video> allVideoList = new ArrayList<Video>();

			// 新作、準新作、旧作の料金。セット料金の本数、料金を取得
			int newPrice = sc.nextInt();
			int normalPrice = sc.nextInt();
			int oldPrice = sc.nextInt();
			int setCount = sc.nextInt();
			int setPrice = sc.nextInt();

			// 上記の入力値が０の場合は標準入力を終え、出力へ
			if (newPrice == 0 && normalPrice == 0 && oldPrice == 0
					&& setCount == 0 && setPrice == 0) {
				break;
			}

			// それぞれのビデオの本数を取得
			int newCount = sc.nextInt();
			int normalCount = sc.nextInt();
			int oldCount = sc.nextInt();

			// 入力値に従い、旧作のインスタンスを作る
			for (int obj_count = 0; obj_count < oldCount; obj_count++) {
				Video Video = new Video(oldPrice, "旧作");
				// ビデオのリストに追加
				allVideoList.add(Video);
			}

			// 入力値に従い、準新作のインスタンスを作る
			for (int obj_count = 0; obj_count < normalCount; obj_count++) {
				Video Video = new Video(normalPrice, "準新作");
				// ビデオのリストに追加
				allVideoList.add(Video);
			}

			// 入力値に従い、新作ビデオのインスタンスを作る
			for (int obj_count = 0; obj_count < newCount; obj_count++) {
				Video Video = new Video(newPrice, "新作");
				// ビデオのリストに追加
				allVideoList.add(Video);
			}

			// 最適なセット料金を適用
			Set set = new Set(setPrice, setCount);
			out.append(set.mostDiscountPrice(allVideoList) + "\n");
		}

		// 結果を出力
		System.out.print(out);

	}
}

/** ビデオクラス */
class Video {

	/** 料金 */
	private int rentalPrice = 0;
	/** 状態 */
	private String value = "";

	/**
	 * 
	 * @param 料金
	 *            　price
	 * @param ビデオの種類
	 *            　val
	 */
	Video(int price, String val) {
		rentalPrice = price;
		value = val;
	}

	/**
	 * ゲッター
	 */
	public int getRentalPrice() {
		return rentalPrice;
	}

	public String getValue() {
		return value;
	}

}

/**
 * セットに関するクラス
 * 
 * @author Admin
 * 
 */
class Set {
	/** セット料金 */
	private int setPrice = 0;
	/** セット料金を適用できる最低本数 */
	private int setCount = 0;

	/** 最適な料金を適用した金額 */
	int mostDiscountPrice = 0;

	/**
	 * コンスタラクタ
	 * 
	 * @param セット料金setP
	 * @param セット料金を適用できる最低本数
	 *            setC
	 */
	Set(int setP, int setC) {

		setPrice = setP;
		setCount = setC;

	}

	/**
	 * 借りるビデオのリストから、最適な料金を出す
	 * 
	 * @param すべてのビデオ
	 *            　all
	 * @return 最安値　DiscountPrice
	 */
	public int mostDiscountPrice(ArrayList<Video> all) {
		int useSetPrice = 0;
		int noUseSetPrice = 0;

		// 並んでいるビデオから、セット適用最低本数分をビデオ料金が高い順に取り出し、セット料金を適用した金額と通常の金額を出す。
		for (int i = 0; i < setCount; i++) {

			useSetPrice += setPrice;
			noUseSetPrice += all.get(i).getRentalPrice();
			// System.out.print(all.get(i).getRentalPrice());
		}

		// セット料金を適用した場合としなかった場合を比較
		// セット料金適用のほうが安かった場合
		if (noUseSetPrice > useSetPrice) {

			// 現在セット料金を適用しているビデオを会計金額に追加
			mostDiscountPrice = useSetPrice;

			// セットを適用していないビデオの中で、現在一番料金の高いビデオとセット料金を比較し、ビデオ料金のほうが高い間はセット料金を適用し続ける
			for (int i = setCount; i < all.size(); i++) {
				if (all.get(i).getRentalPrice() >= setPrice) {
					mostDiscountPrice += setPrice;
				} else {
					// セット料金のほうが高くなった場合はビデオ料金を適用
					mostDiscountPrice += all.get(i).getRentalPrice();
				}
			}
		} else {

			// セット料金適用のほうが高かった場合
			// 通常料金を適用
			for (Video video : all) {
				mostDiscountPrice += video.getRentalPrice();
			}
		}

		return mostDiscountPrice;
	}
}