5 * Solution for NEERC'2009 Problem J: Java Certification
6 * This solution is slow (uses backtracking)
7 * This solution checks correctness of the input.
8 * @author Roman Elizarov
10 public class javacert_re_backtrack
{
12 public static void main(String
[] args
) throws Exception
{
13 new javacert_re_backtrack().go();
16 void go() throws Exception
{
27 void read() throws Exception
{
28 Scanner in
= new Scanner(new File("javacert.in"));
29 in
.useLocale(Locale
.US
);
34 assert k
>= 0 && k
<= n
;
35 assert n
>= 1 && n
<= 100;
36 assert m
>= 1 && m
<= 10;
38 for (int i
= 0; i
< m
; i
++) {
41 assert p
[i
] >= 0 && p
[i
] <= 100;
50 Pair(int wi
, int ni
) {
56 public String
toString() {
57 return wi
+ " " + ni
+ " " + (100.0*(ni
- wi
) / ni
);
72 soldiff
= Integer
.MAX_VALUE
;
73 find(0, 0, 0, Integer
.MAX_VALUE
, Integer
.MIN_VALUE
);
76 private void buildPairs() {
77 llp
= new ArrayList
<List
<Pair
>>();
78 for (int i
= 0; i
< m
; i
++) {
79 llp
.add(new ArrayList
<Pair
>());
81 for (int ni
= 1; ni
<= n
; ni
++) {
82 for (int wi
= 0; wi
<= ni
; wi
++) {
83 int ppp
= 100 * (ni
- wi
);
84 int pp
= (2 * ppp
+ ni
) / (2 * ni
);
85 if (2 * ppp
% ni
== 0 && 2 * ppp
/ ni
% 2 == 1 && pp
% 2 == 1)
87 for (int i
= 0; i
< m
; i
++) {
89 llp
.get(i
).add(new Pair(wi
, ni
));
95 private void sortPairs() {
96 final double mid
= n
/ m
;
97 for (int i
= 0; i
< m
; i
++) {
98 Collections
.sort(llp
.get(i
), new Comparator
<Pair
>() {
99 public int compare(Pair p1
, Pair p2
) {
100 double d1
= Math
.abs(p1
.ni
- mid
);
101 double d2
= Math
.abs(p2
.ni
- mid
);
102 return Double
.compare(d1
, d2
);
108 void find(int i
, int ws
, int ns
, int minni
, int maxni
) {
109 if (ns
> n
|| ws
> w
)
111 int diff
= maxni
- minni
;
115 if (ns
< n
|| ws
< w
)
118 sol
= cursol
.clone();
121 for (Pair p
: llp
.get(i
)) {
123 find(i
+ 1, ws
+ p
.wi
, ns
+ p
.ni
, Math
.min(minni
, p
.ni
), Math
.max(maxni
, p
.ni
));
127 void write() throws Exception
{
128 PrintWriter out
= new PrintWriter("javacert.out");
129 for (int i
= 0; i
< m
; i
++) {
130 out
.printf("%d %d%n", sol
[i
].wi
, sol
[i
].ni
);
135 //----------------- just for validation ------------------
138 * Strict scanner to veryfy 100% correspondence between input files and input file format specification.
139 * It is a drop-in replacement for {@link java.util.Scanner} that could be added to a soulution source
140 * (cut-and-paste) without breaking its ability to work with {@link java.util.Scanner}.
142 public class Scanner
{
143 private final BufferedReader in
;
144 private String line
= "";
147 private boolean localeset
;
149 public Scanner(File source
) throws FileNotFoundException
{
150 in
= new BufferedReader(new FileReader(source
));
154 public void close() {
155 assert line
== null : "Extra data at the end of file";
158 } catch (IOException e
) {
159 throw new AssertionError("Failed to close with " + e
);
163 public void nextLine() {
164 assert line
!= null : "EOF";
165 assert pos
== line
.length() : "Extra characters on line " + lineNo
;
167 line
= in
.readLine();
168 } catch (IOException e
) {
169 throw new AssertionError("Failed to read line with " + e
);
175 public String
next() {
176 assert line
!= null : "EOF";
177 assert line
.length() > 0 : "Empty line " + lineNo
;
179 assert line
.charAt(0) > ' ' : "Line " + lineNo
+ " starts with whitespace";
181 assert pos
< line
.length() : "Line " + lineNo
+ " is over";
182 assert line
.charAt(pos
) == ' ' : "Wrong whitespace on line " + lineNo
;
184 assert pos
< line
.length() : "Line " + lineNo
+ " is over";
185 assert line
.charAt(0) > ' ' : "Line " + lineNo
+ " has double whitespace";
187 StringBuilder sb
= new StringBuilder();
188 while (pos
< line
.length() && line
.charAt(pos
) > ' ')
189 sb
.append(line
.charAt(pos
++));
190 return sb
.toString();
193 public int nextInt() {
195 assert s
.length() == 1 || s
.charAt(0) != '0' : "Extra leading zero in number " + s
+ " on line " + lineNo
;
196 assert s
.charAt(0) != '+' : "Extra leading '+' in number " + s
+ " on line " + lineNo
;
198 return Integer
.parseInt(s
);
199 } catch (NumberFormatException e
) {
200 throw new AssertionError("Malformed number " + s
+ " on line " + lineNo
);
204 public double nextDouble() {
205 assert localeset
: "Locale must be set with useLocale(Locale.US)";
207 assert s
.length() == 1 || s
.startsWith("0.") || s
.charAt(0) != '0' : "Extra leading zero in number " + s
+ " on line " + lineNo
;
208 assert s
.charAt(0) != '+' : "Extra leading '+' in number " + s
+ " on line " + lineNo
;
210 return Double
.parseDouble(s
);
211 } catch (NumberFormatException e
) {
212 throw new AssertionError("Malformed number " + s
+ " on line " + lineNo
);
216 public void useLocale(Locale locale
) {
217 assert locale
== Locale
.US
;