Advent Of Code 2023 Day 24 Solution

\[\texttt{Description} \]

\(n\) 个雪球,每个雪球用 \(6\) 个整数 \(x_i,y_i,z_i,u_i,v_i,w_i\) 表述,代表雪球 \(i\)\(t\) 时刻的位置是 \((x_i+u_it,y_i+v_it,z_i+w_it)\)

\(\texttt{Part 1 : }\)在只考虑 \(xy\) 平面的情况下,有多少对雪球的轨迹会在某一个特定的方形区间内相交?

\(\texttt{Part 2 : }\)现在有一个魔法雪球,它在与每一个雪球在 整数时间刻 时相遇。问这个雪球的坐标之和是多少,保证只有唯一解。

\(\texttt{Constaints : }n\le 300\).


\[\texttt{Part 1} \]

直接枚举每一对雪球,通过代数计算交点判断即可。

import sys
import re

cr=lambda a1,b1,c1,d1,a2,b2,c2,d2: (d2*a2+c2*b1-c2*b2-d2*a1)/(d2*c1-c2*d1) if d2*c1-c2*d1!=0 else 1e18
val=lambda k1,b1,x: b1+k1*x
fit=lambda l,r,x: x>=l and x<=r

a=open(0).readlines()
l,r=map(int,a[0].split(' '))
a=list(map(lambda it:re.findall("[0-9-]+",it),a[1:]))
a=list(map(lambda it:list(map(int,it)),a))

tar=0

for i in range(len(a)):
    for j in range(i+1,len(a)):
        s=cr(a[i][0],a[i][1],a[i][3],a[i][4],a[j][0],a[j][1],a[j][3],a[j][4])
        t=cr(a[j][0],a[j][1],a[j][3],a[j][4],a[i][0],a[i][1],a[i][3],a[i][4])
        if s<0 or t<0 : continue
        if fit(l,r,val(a[i][3],a[i][0],s)) and fit(l,r,val(a[i][4],a[i][1],s)):
            tar+=1
print(tar)

\[\texttt{Part 2} \]

我们发现坐标很难直接求出,所以我们考虑先求速度。

假设我们先求 \(u_0\)

我们发现,对于两个拥有相同 \(u_i\) 值的两个雪球,在以他们为参考系的情况下,只有魔法雪球会动。

设他们的 \(x\) 坐标为 \(x_i\),\(x_j\),那么由于魔法雪球与他们只在整数时间刻时相遇,所以相遇的时间差也是整数。

\(\Large\frac{x_i-x_0}{u_i-u_0}-\frac{x_j-x_0}{u_i-u_0}=\frac{x_i-x_j}{u_i-u_0}\) 是整数。

即:

\[x_i-x_j\equiv 0\pmod{u_i-u_0} \]

那么我们就拥有了一堆同余的方程需要满足。

大胆假设速度必然不会很大,所以在 \([-5000,5000]\) 中暴力试数即可。

同理,\(v_0\)\(w_0\) 也可以求出。

现在,我们求出速度以后,以魔法雪球为参考系。由于所有雪球都与它相遇,所以此时 所有雪球的轨迹相交于一点

判断所有雪球的轨迹是否相交于一点后焦点就是答案。

Desmos 演示

import sys
import re

def equ(x,y):
    return x==y or x==-1e18 or y==-1e18

def calc(x):
    tx=[]
    for it in range(-5000,5000):
        flag=True
        for (l,vx) in x:
            if it==vx or l%(it-vx):
                flag=False
        if flag: tx.append(it)
    return tx


a=list(map(lambda it:re.findall(r"[\d-]+",it),open(0).readlines()))
a=list(map(lambda it:list(map(int,it)),a))

x,y,z,tar=[],[],[],[]

for i in range(len(a)):
    for j in range(i+1,len(a)):
        if a[i][3]==a[j][3]:
            x.append((abs(a[i][0]-a[j][0]),a[i][3]))
        if a[i][4]==a[j][4]:
            y.append((abs(a[i][1]-a[j][1]),a[i][4]))
        if a[i][5]==a[j][5]:
            z.append((abs(a[i][2]-a[j][2]),a[i][5]))
tx,ty,tz=calc(x),calc(y),calc(z)

for vx in tx:
    for vy in ty:
        for vz in tz:
            la,lb=a[0],a[1]
            x0,y0,z0,u0,v0,w0=la[0],la[1],la[2],la[3]-vx,la[4]-vy,la[5]-vz
            x1,y1,z1,u1,v1,w1=lb[0],lb[1],lb[2],lb[3]-vx,lb[4]-vy,lb[5]-vz
            t1=(u1*y0-u1*y1-v1*x0+v1*x1)/(v1*u0-v0*u1)
            t2=(x0-x1+u0*t1)/u1
            if t1<0 or t2<0: continue
            res=(x0+u0*t1,y0+v0*t1,z0+w0*t1)
            if int(res[0])!=res[0] or int(res[1])!=res[1] or int(res[2])!=res[2]:
                continue
            flag=True
            for (x2,y2,z2,u2,v2,w2) in a:
                tt1=(res[0]-x2)/(u2-vx) if u2!=vx else (-1e18 if res[0]==x2 else 1e18+vx)
                tt2=(res[1]-y2)/(v2-vy) if v2!=vy else (-1e18 if res[1]==y2 else 1e18+vy)
                tt3=(res[2]-z2)/(w2-vz) if w2!=vz else (-1e18 if res[2]==z2 else 1e18+vz)
                flag&=(equ(tt1,tt2) and equ(tt2,tt3) and equ(tt1,tt3))
            if not flag: continue
            tar.append(((int(res[0]),int(res[1]),int(res[2])),(vx,vy,vz),int(sum(res))))
print('\n'.join(map(lambda it:str(it)[1:-1],tar)))
posted @ 2024-12-04 20:36  静谧幽蓝  阅读(23)  评论(0)    收藏  举报