###前提・実現したいこと
このページの問題を解きたいです。
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3886
概要は、いくつかの個数の整数を要素に持つ集合があり、その中から適当な整数を選び出して和をとると、指定した値にできるかどうかを判定するという問題です。集合の要素の個数、集合の要素の値、目標値は全て自分で指定します。
実行例は以下の通りです。
//Sample Input 4 // テストケース数 25 // 和を25にしたい 4 // 集合内にいくつの整数を要素として持つか 10 12 5 7 // 集合内の4つの整数要素を指定 925 // 和を925にしたい 10 // 集合の要素数は10 45 15 120 500 235 58 6 12 175 70 // 集合内の要素となる10個の整数 120 // 以下繰り返し 5 25 25 25 25 25 0 2 13 567 //Sample Output NO // その集合では和を25にできない YES // 和を925にできる NO YES
方針がわかりませんでしたが、いろいろ調べてみると以下のようなサイトを見つけたので、
ここに書いてある方針に倣い、動的計画法を使ってコードを書きました。
http://gushwell.ifdef.jp/etude/SubsetSum.html
###発生している問題・エラーメッセージ
コマンドプロンプト上で、上記のSample Input、並びにUDebug(https://www.udebug.com/UVa/12455)にある2つのInput例で試したところ、全く同じ結果が出力されました。
それにも関わらず、UVaでSubmitするとRuntime Errorとなってしまいます。
Runtime Errorについて調べたところ、「配列よりも大きな要素番号にアクセスしたり、ポインタの使用方法が間違っていたりして、セグメントエラーが発生することが主な原因」となるそうですが、もしそうだとしたら、コマンドプロンプト上で実行した時点で、結果が出力される前に何かしらのエラー文が出るのでは?と思いました。(自分はプログラミングができないので、十中八九この推測が違うんだろうとは思いますが)
せめてUVaが何行目でRuntime Errorとなったのか出してくれればいいのですが……
原因がまるで分らないので誰か助けてください……
###該当のソースコード
java
1import java.util.StringTokenizer; 2import java.io.*; 3 4class Bars { 5 public static void main (String[] args) { 6 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 7 8 try { 9 String line; 10 StringTokenizer token; 11 line = br.readLine(); 12 int testcase = Integer.parseInt(line); // テストケース数 13 14 for(int a=0; a<testcase; a++) { // テストケース数だけ一連の流れを繰り返す 15 line = br.readLine(); 16 int target = Integer.parseInt(line); // 目標値 和をこの値にできるかどうか 17 18 if(target==0) System.out.println("YES"); 19 // 目標値が0なら空集合を取れば和を0にできるのでYES 20 else { 21 line = br.readLine(); 22 int num = Integer.parseInt(line); // 集合の要素数 23 24 int tmp; 25 int ex = 0; // 目標値を超えた要素の値が来た時、ex(=exception)をインクリメント 26 int[] bar = new int[num]; // 要素数分の配列 27 line = br.readLine(); 28 token = new StringTokenizer(line, " "); 29 30 for(int i=0; i<num; i++) { 31 tmp = Integer.parseInt(token.nextToken()); 32 if(tmp<=target) bar[i-ex] = tmp; //要素が目標値より小さければ配列に入れる 33 else ex++; // そうでない場合は配列に入れずにexをインクリメント 34 } // 2行上でbar[i-ex]としているのは、例外が来ると要素数が減るため 35 36 num -= ex; // exの分だけ要素数が入力時よりも減る 37 38// この先は方針の参考にしたサイトに書いてある手順をコードにしました 39 int[] array = new int[target+1]; // 和が0~和がtarget → 大きさがtarget+1の配列 40 array[0] = 0; // 配列の先頭には0、あとは全て-1を入れて初期化 41 for(int i=1; i<=target; i++) array[i] = -1; 42 boolean judge = false; // 和がtargetになるとわかったらjudgeをtrueに書き換える 43 44 // nは参考サイトのnと同じ、jは同サイトにおけるi 45 for(int i=0; i<num; i++) { 46 int n = bar[i]; 47 48 for(int j=target; j>=0; j--) { 49 if(array[j]!=-1) { 50 if(n+j<=target && array[n+j]==-1) array[n+j] = n; 51 } 52 } 53 54 // array[target] (配列の最後)に-1以外が入った瞬間、それは和をtargetにできるということを意味する 55 if(array[target]!=-1) { 56 judge = true; 57 break; 58 } 59 } 60 61 if(judge) System.out.println("YES"); 62 else System.out.println("NO"); 63 } 64 } 65 66 } catch(IOException e) { 67 System.out.println("IOException" + e); 68 System.exit(1); 69 } 70 } 71} 72
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/05/11 17:09
2017/05/11 17:14
2017/05/11 17:46