第一次用Java代碼過搜索+剪枝的題目啊,不容易啊……,而且還是參考了后面的Analysis,-_-!
不過里面的那個Hash的剪枝還是很強(qiáng)大的,再一次說明了學(xué)好數(shù)學(xué)的重要
同時,再一次證明了Java有多慢,C++肯定不用加最后的剪枝就過了,但是Java就不行
而且有一個點(diǎn)居然要1.5秒,真是不可思議。
待會兒我再試試Analysis里面的代碼,看看有多快,是不是Static的要比正常的寫快。
算法沒啥好說的,就是生成,把F+R個數(shù)生成出來,然后用那個最大ratio是最小ratio的三倍做一個剪枝
我之前還打了一個表,所有的數(shù)的ratio的表,然后后面直接訪問這個表,而不是去現(xiàn)去除
但是發(fā)現(xiàn)好像左右不大。
剩下的就是那個Hash的優(yōu)化了,很強(qiáng)大,就好象題目里說的那樣,就是看F生成好之后的比率
比如1 3 5 7,前兩個是F的,后兩個是R的,那么它的variance和2 6 10 14是一樣的,這個不用我解釋吧
這樣的話呢,同一個比率的就不用再做第二次了。
自己沒有去嚴(yán)格的證明這個剪枝的正確性,但是想想證明應(yīng)該不太難。
同一個ratio的話肯定取前面那組,如果是不同的ratio呢?
現(xiàn)在的問題就是,如果是不同的ratio,后面的正確的組會不會被前面的不小心剪掉?;蛘吆竺娴倪@組根本沒必要。
如果是根本沒必要的話,那么這個剪枝肯定就是正確的了。
其實(shí)這個剪枝是正確的,因?yàn)樵谀阌帽热?,3的時候,你就試過了后面所有的不同組合了。
那么當(dāng)你擴(kuò)大1,3到2,6時,我們可以看看USACO后面的解釋的那個例子來。
39/16 = 2.43750000000000000000
40/16 = 2.50000000000000000000
39/15 = 2.60000000000000000000
40/15 = 2.66666666666666666666
39/14 = 2.78571428571428571428
40/14 = 2.85714285714285714285
39/13 = 3.00000000000000000000
40/13 = 3.07692307692307692307
39/12 = 3.25000000000000000000
40/12 = 3.33333333333333333333
|
就相當(dāng)于這些ratio全都翻了一倍,那樣的話,variance當(dāng)然不會變
所以個剪枝是正確的。
貼一下代碼:
1 import java.io.*;
2 import java.util.*;
3 /*
4 ID: yanglei4
5 LANG: JAVA
6 TASK:cowcycle
7 */
8 public class cowcycle{
9 public double[][] ratio = new double[81][41];
10 int F,R,F1,F2,R1,R2;
11 public int[] s1;
12 public int[] s2;
13 double min = 1000000;
14 static String[] hash;
15 public int[] ans1;
16 public int[] ans2;
17
18 public static boolean contains(String str) {
19 int num = str.hashCode();
20 if(num<0) num = -num;
21 int p = num % hash.length;
22 while(hash[p]!=null)
23 if(str.equals(hash[p])) return true;
24 else if(p==hash.length-1) p=0;
25 else p++;
26 hash[p]=str;
27 return false;
28 }
29
30 public void DFS_F(int step,int start) {
31 if (step == F + 1) {
32 StringBuffer str = new StringBuffer();
33 for(int i = 2;i <= F;i++)
34 str.append((int)(100*(double)s1[i]/s1[1]));
35 if(contains(str.toString())) return;
36
37 DFS_R(1,R1);
38 return;
39 }
40 for (int i = start; i <= F2 - (F - step); i++) {
41 s1[step] = i;
42 DFS_F(step + 1, i + 1);
43 }
44 }
45
46 public void DFS_R(int step,int start) {
47 if (step == R + 1) {
48 if (s1[F] * s2[R] < 3 * s1[1] * s2[1])
49 return;
50 count();
51 return;
52 }
53 for (int i = start; i <= R2 - (R - step); i++) {
54 s2[step] = i;
55 DFS_R(step + 1, i + 1);
56 }
57 }
58
59 public double count() {
60 double[] rate = new double[R * F + 1];
61 double[] diff = new double[R * F + 1];
62 double sum = 0;
63 double sumf = 0;
64 int l = 1;
65 for (int i = 1; i <= F; i++)
66 for (int j = 1; j <= R; j++)
67 rate[l++] = ratio[s1[i]][s2[j]];
68
69 Arrays.sort(rate);
70
71 for (int i = 1; i <= F * R - 1; i++) {
72 diff[i] = rate[i + 1] - rate[i];
73 sum += diff[i];
74 sumf += diff[i] * diff[i];
75 }
76 double avg = sum / (F * R - 1);
77 double vf = sumf - sum * avg;
78 if (vf < min) {
79 min = vf;
80 for (int i = 1; i <= F; i++) ans1[i] = s1[i];
81 for (int i = 1; i <= R; i++) ans2[i] = s2[i];
82 }
83 return 0.0;
84 }
85
86 public void done() throws IOException {
87 for (int i = 25; i <= 80; i++)
88 for (int j = 5; j <= 40; j++)
89 ratio[i][j] = (double)i / j;
90
91 BufferedReader f = new BufferedReader(new FileReader("cowcycle.in"));
92 PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("cowcycle.out")));
93 StringTokenizer st = new StringTokenizer(f.readLine());
94 F = Integer.parseInt(st.nextToken());
95 R = Integer.parseInt(st.nextToken());
96 st = new StringTokenizer(f.readLine());
97 F1 = Integer.parseInt(st.nextToken());
98 F2 = Integer.parseInt(st.nextToken());
99 R1 = Integer.parseInt(st.nextToken());
100 R2 = Integer.parseInt(st.nextToken());
101 s1 = new int[F + 1];
102 s2 = new int[R + 1];
103 ans1 = new int[F + 1];
104 ans2 = new int[R + 1];
105 hash = new String[50003];
106
107 DFS_F(1,F1);
108
109 for (int i = 1; i <= F - 1; i++)
110 out.print(ans1[i] + " ");
111 out.println(ans1[F]);
112
113 for (int i = 1; i <= R - 1; i++)
114 out.print(ans2[i] + " ");
115 out.println(ans2[R]);
116
117 out.close();
118 }
119
120 public static void main(String[] args) throws IOException {
121 cowcycle t = new cowcycle();
122 t.done();
123 System.exit(0);
124 }
125 }
126