算法思维训练之几何及构造详解及实战演练 (2月28日)

106 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划·2月更文挑战」的第21天,点击查看活动详情

牛客小白月赛2 B小马过河(几何)

image.png

题解:

P(px,py)U(ux,uy)V(vx,vy)P(px, py),U(ux, uy),V(vx, vy)

有三个点的位置,通过UVU,V两个点的坐标可以求出直线UVUV的斜率k1k_1

直线UVUV中:有斜率,有点的坐标,可以通过点斜式写出直线UVUV的解析式

PP点,作PAUVPA⊥UV通过两直线垂直,k1k2=1k_1·k_2 = -1,求出直线PAPA的斜率k2k_2

直线PAPA通过点P(pxpy)P(px,py) 那么也可以通过点斜式写出直线PAPA的解析式

直线UVUV和直线PAPA的交点即 要求的垂足。

特殊情况,特殊判断:ux==yxuy==vyux==yx,uy==vy

常规情况:

直线UVUVk=vyvxuyuxk=\frac{vy-vx}{uy-ux}

直线UVUV通过vv点且斜率为kk

直线UVUV的解析式:yvy=k(xvx)y-vy=k(x-vx)

PP点,作PAUVPA⊥UV通过两直线垂直,则直线UV的斜率为 1k-\frac{1}{k}

直线PAPA的解析式:ypy=1k(xpx)y-py=-\frac{1}{k}(x-px)

联立直线UVUVPAPA

vy+k(xvx)=py+[1k(xpx)]v_y+k(x-v_x)=p_y+[-\frac{1}{k}(x-p_x)]

vy+kxkvx=pyxk+pxkv_y+kx-kv_x=p_y-\frac{x}{k}+\frac{p_x}{k}

(k+1k)x=pyvy+kvx+pxk(k+\frac{1}{k})x=p_y-v_y+kv_x+\frac{p_x}{k}

x=pyvy+kvx+pxkk2+1kx=\frac{p_y-v_y+kv_x+\frac{p_x}{k}}{\frac{k^2+1}{k}}

x=k2vxkvy+px+kpyk2+1x = \frac{k^2v_x-kv_y+p_x+kp_y}{k^2+1}

y=k(xvx)+vyy = k(x-v_x)+v_y

int main() {
    int _, cin >> _;
    while (_--) {
        double px, py, ux, uy, vx, vy;
        cin >> px >> py >> ux >> uy >> vx >> vy;
        if (ux == vx) printf("%.7lf %.7lf\n", ux, py);
        else if (uy == vy) printf("%.7lf %.7lf\n", px, uy);
        else {
            double k = (vy - uy) / (vx - ux);
            double x = (k * k * vx - k * vy + px + k * py) / (k * k + 1);
            double y = k * (x - vx) + vy;
            printf("%.7lf %.7lf\n", x, y);
        }
    }
    return 0;
}

# 牛客小白月赛2 J-美(构造)

image.png

选美大赛,这套题有点阴间

题意,要求选出差值的和最大,依旧是构造题

构造:一个最大,一个最小,一个次大,一个次小 ... 以此类推,这样的差之和最大。

举例:1 2 3 4 5

结果:5 1 4 2 3

注意:当 i = 1时,R0 = Rn,所以初始化 ans = abs(b[1] - b[n])

那么就是注意一下下标即可。

const int N = 100010;
int a[N], b[N];
signed main() {
    int n, cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    sort(a + 1, a + n + 1);
    int idx = 0;
    for(int i = 1; i <= n; i += 2) b[i] = a[++idx];
    if (n % 2) for (int i = n - 1; i > 0; i -= 2) b[i] = a[++idx];
    else for (int i = n; i > 0; i -= 2) b[i] = a[++idx];
    int ans = abs(b[1] - b[n]);
    for (int i = 2; i <= n; i++) ans += abs(b[i] - b[i - 1]);
    cout << ans << endl;
    return 0;
}