private void solveC() {
try (Scanner scanner = new Scanner(System.in)) {
int numD = scanner.nextInt();
int numG = scanner.nextInt();
//色々初期計算しとけばバグ減らせそうなので多めに
long[][] wk = new long[10][5];
for (int i = 0; i < numD; i++) {
wk[i][0] = (i + 1) * 100;//単価
wk[i][1] = scanner.nextLong();//問題数
wk[i][2] = scanner.nextLong();//コンプリートボーナス
wk[i][3] = (wk[i][0] * wk[i][1]) + wk[i][2];//コンプリート総額
}
long operationNum = 999999999;
int[] mask = new int[10];
/*
* mask回数分ループ
*/
for (int i = 0; i < Math.pow(2, 10); i++) {
/*
* mask生成
* ちなみにこのマスクは、
* 配点の低いやつをコンプリート -> 配点の高いやつをコンプリート
* という順序のmaskを生成しています。
*/
int maskNum = i;
int cnt = 0;
while (maskNum > 0) {
mask[cnt] = maskNum % 2;
cnt++;
maskNum /= 2;
}
//処理用変数:目標点数
int wkG = numG;
//処理用変数:操作回数
int wkOperationNum = 0;
/*
* maskの分だけループする
*/
for (int j = 0; j < mask.length; j++) {
/*
* 使う対象の問題
* 全問解いてコンプリートもらうと決めたやつ -> mask[i]=1
* &
* 取り込めている奴 -> wk[i][0] > 0
*/
if (mask[j] == 1 && wk[j][0] > 0) {
/*
* 使うと決めたので全部解く
* コンプリート総額を利用
*/
wkG -= wk[j][3];
/*
* 問題を解いた回数=問題数 を記録
* これでこの問題は全て終了
*/
wkOperationNum += wk[j][1];
}
/*
* 結果として取得したい点数を達成済みの場合はこのマスクはbreak
* この後の点数合わせは不要
*/
if (wkG <= 0) {
//break前に問題数を記録
operationNum = Math.min(operationNum, wkOperationNum);
break;
}
}
/*
* 希望点数に達していないため、まだ解かないといけない問題がある
*/
if (wkG > 0) {
/*
* 今回のループの対象は、maskしていない=コンプリートしないと決めた問題
* ただし、配点の高い順から
* 配点の高さはwk[i]のiの大きい順から
* なので、mask.length-1ではなく、10でもwk.length-1でもどれでもよい
* 解く手数を減らしたいなら配転の高いのからやったほうがいいよね
*/
outside: for (int j = mask.length - 1; j >= 0; j--) {
/*
* 使う対象の問題
* 全問解いてコンプリートもらわないやつ -> mask[i]=0
* &
* 取り込めている奴 -> wk[i][0] > 0
* なので、このループのwkG-=ではコンプリートボーナスつかいません
*/
if (mask[j] == 0 && wk[j][0] > 0) {
/*
* 解く対象の配点問題で問題数をループ
*/
for (int k = 0; k < wk[j][1]; k++) {
//1個ずつ解いて回数をカウントアップ
wkG -= wk[j][0];
wkOperationNum++;
/*
* これ以上不要ならbreak
* 汚いけど外まで飛ぶ
*/
if (wkG <= 0) {
//break前に問題数を記録
operationNum = Math.min(operationNum, wkOperationNum);
break outside;
}
}
}
}
/*
* ここまでくるとこのmaskでは解きようがない
* 全ての問題解いてもクリアできない点ということなので
*/
}
}
System.out.println(operationNum);
}
}