Java 915 * 0.75 = 686.25
import java.util.*;class E implements Comparable<E>{static
int n,m,t,u;byte[]a;int k=2,b,d;E(){a=new byte[5];a[1]=13;}E(E
x){a=Arrays.copyOf(x.a,n+1);k=x.k;d=x.d;b=x.b;}int
g(int x){return(a[x]+1)%3-1;}void s(int x,int y){a[x]=(byte)(a[x]/3*3+(y+3)%3);}void
S(int x,int y){a[x]=(byte)(a[x]%3+(y+3)*3);}E
w(int x){if(g(k)==-x)return null;E e=new E(this);e.s(k,x);e.S(e.k++,x);for(m=0;++m<k;)if(k%m<1){u=e.a[m]/3-3+x;if(u==(k<9?2:4)*x)return
null;e.S(m,u);if(u==3*x){e.b++;if(k+m<=n){if(e.g(k+m)==x)return
null;e.s(k+m,-x);}}}return e;}public int compareTo(E o){m=d-o.d+(b-o.b)/60+(o.k-k)/150;return
m==0?o.k-k:m;}public static void main(String[]a){n=Integer.valueOf(a[0]);Queue<E>q=new PriorityQueue<>();q.add(new
E());for(;;){E x=q.remove(),y;if(x.k>n){for(t=0;++t<x.k;)System.out.print((x.g(t)+1)/2);return;}t=x.g(x.k<9?1:x.k%9==0?x.k/9:x.k%9);y=x.w(t);if(y!=null)q.add(y);y=x.w(-t);if(y!=null){y.d++;q.add(y);}}}}
输入被当作命令行参数。
这会尝试几乎所有的可能性(唯一的限制是前8个步骤应只在-1..1范围内进行),使用魔术伏都教启发法逐步选择最先尝试的方法。
在我的(相当快)的计算机上,它可以在1秒内解决2000甚至4000。需要更多的RAM才能获得更大的数量;我在8GB范围内解决的最大输入是5023,耗时约30秒。
要求加分的2000步解决方案的十进制表示形式:
67629177464446960798008264442022667063957880432486338092706841703491740570274032860458934082821213021464065304260003487277917407152662394728833698812373924467640518368465012204980858438160127647802572983143425507448999967241207186701518207195015015739598846687434709056793597015487555707466358473564611432637890414593517116857771284711814076853125419306285869381974622557155019992727242896503018802441210966188045211779436703341152749688824296759097963388158731237092792251164105828728858516951458791084595247591674731645830905744761534078963607725435881491831508342871545788662307953494333833994658998
Yb
在CJam中附加到它,以转换回二进制文件。
关于启发式:首先,我正在使用一种模式:每9个步骤尝试重复前9个步骤,除了每(9 * x)个步骤尝试重复第x个步骤。这是从我在python答案中下载并使用(硬编码)的解决方案中得到的启发。
我一直在跟踪偏离模式的次数,以及到达“边缘”的次数(距离死亡仅一步之遥)。启发式函数基本上是这两个数字和到目前为止已执行的步数的加权组合。
可以进一步调整试探法以提高速度,并且也有几种方法可以向其中添加随机因子。
实际上,我刚刚阅读了有关此问题的乘法函数,并且看起来可以提供重大改进(TODO:稍后实施)。
取消评论并评论:
import java.util.*;
public class Erdos implements Comparable<Erdos> {
static int n; // input (requested number of steps)
static int m, t, u; // auxiliary variables
byte[] a; // keeps each step and sum combined into 1 byte
int k = 2; // number of steps + 1 (steps are 1-based)
int edge; // number of times we got to an edge
int diff; // number of differences from the expected pattern
// start with one step
Erdos() {
a = new byte[5];
set(1, 1);
setSum(1, 1);
}
// copy constructor
Erdos(Erdos x) {
a = Arrays.copyOf(x.a, n + 1);
k = x.k;
diff = x.diff;
edge = x.edge;
}
// get the x'th step (can be -1, 0 or 1)
int get(int x) {
return (a[x] + 1) % 3 - 1;
}
// set the x'th step
void set(int x, int y) {
a[x] = (byte) (a[x] / 3 * 3 + (y + 3) % 3);
}
// get the sum of every x'th step (should be within -3..3)
int getSum(int x) {
return a[x] / 3 - 3;
}
// set the sum of every x'th step
void setSum(int x, int y) {
a[x] = (byte) (a[x] % 3 + (y + 3) * 3);
}
// try to add a step with value x (1 or -1)
Erdos grow(int x) {
if (get(k) == -x) // predetermined step doesn't match
return null;
Erdos e = new Erdos(this);
e.set(k, x);
e.setSum(e.k++, x);
for (m = 0; ++m < k;)
if (k % m < 1) { // check all divisors of k
u = e.getSum(m) + x; // updated sum
if (u == (k < 9 ? 2 : 4) * x) // use limit 2 for the first 8 steps, 4 for the rest
return null; // dead
e.setSum(m, u);
if (u == 3 * x) { // we're at an edge
e.edge++;
if (k + m <= n) { // predetermine future step - should be going back
if (e.get(k + m) == x) // conflict
return null;
e.set(k + m, -x);
}
}
}
return e;
}
public int compareTo(Erdos o) { // heuristic function
m = diff - o.diff + (edge - o.edge) / 60 + (o.k - k) / 150;
return m == 0 ? o.k - k : m;
}
public static void main(String[] a) {
n = Integer.valueOf(a[0]);
Queue<Erdos> q = new PriorityQueue<>();
q.add(new Erdos());
for (;;) {
Erdos x = q.remove(), y;
if (x.k > n) { // we made it
for (t = 0; ++t < x.k;)
System.out.print((x.get(t) + 1) / 2);
return;
}
t = x.get(x.k < 9 ? 1 : x.k % 9 == 0 ? x.k / 9 : x.k % 9); // next step based on the pattern
y = x.grow(t);
if (y != null)
q.add(y);
y = x.grow(-t);
if (y != null) {
y.diff++;
q.add(y);
}
}
}
}
n=13000
,它的前2000条指令会赢得奖金吗?似乎毫无意义,所以您可能还有其他意思吗?