1 条题解

  • 0
    @ 2025-8-24 22:51:09

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Diaоsi
    Enemy of God

    搬运于2025-08-24 22:51:09,当前版本为作者最后更新于2024-05-21 17:24:45,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    [EC Final 2022] Map

    看着挺吓人的一道计算几何,其实写起来挺简单(?

    首先最优的方案一定是先进行若干次连续的 ff,然后走一小段,再进行若干次连续的 f1f^{-1},这样一定是最优的。

    为什么呢?假设在走了一段路之后再进行 ff,那么这段路肯定放在 ff 之后走更优,因为地图中的路程一定更短。先 f1f^{-1} 再走的情况同理。

    所以只需要枚举 fff1f^{-1} 的次数,由于 nn 很小,所以可以 O(n2)\mathcal{O}\big(n^2\big) 枚举。

    接下来重点在于如何优雅地实现 ff,不妨利用矩形的正交性,以矩形的左下角为原点建系:

    3

    设当前坐标在 DABDAB 坐标系下对应的向量为 u\mathbf{u},我们只需要把 u\mathbf{u} 沿着 ADADABAB 进行分解,然后把坐标系变换到 HEFHEF,再按照两个矩形的相似比进行伸缩变换就可以合成 v\mathbf{v}

    具体变换可以用点乘实现,可以参考代码。

    时间复杂度 O(n2)\mathcal{O}(n^2)

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    typedef long long ll;
    typedef long double ld;
    using namespace std;
    const int N=110,M=10010,INF=0x3f3f3f3f;
    const ld inf=2e18;
    inline int max(int x,int y){return x>y?x:y;}
    inline int min(int x,int y){return x<y?x:y;}
    inline void swap(int &x,int &y){x^=y^=x^=y;}
    struct node{
    	ld x,y;
    	node(ld xx=0,ld yy=0){x=xx,y=yy;}
    	void in(){scanf("%Lf%Lf",&x,&y);}
    }A[5],B[5],S,T;
    
    node operator +(node a,node b){return node(a.x+b.x,a.y+b.y);}
    node operator -(node a,node b){return node(a.x-b.x,a.y-b.y);}
    ld operator *(node a,node b){return a.x*b.x+a.y*b.y;}
    ld operator ^(node a,node b){return a.x*b.y-a.y*b.x;}
    
    node operator *(ld x,node a){return node(x*a.x,x*a.y);}
    
    ld sqr(ld x){return x*x;}
    ld dis(node a,node b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
    
    int _,n,k;
    ld ans;
    
    node f(node p){
    	node ao=A[1],ai=A[4]-A[1],aj=A[2]-A[1];
    	node bo=B[1],bi=B[4]-B[1],bj=B[2]-B[1];
    	p=node(((p-ao)*ai)/(ai*ai),((p-ao)*aj)/(aj*aj));
    	return bo+p.x*bi+p.y*bj;
    }
    void solve(){
    	ans=inf;
    	for(int i=1;i<=4;i++)A[i].in();
    	for(int i=1;i<=4;i++)B[i].in();
    	S.in();T.in();
    	scanf("%d%d",&k,&n);
    	node u=S;
    	for(int i=0;i<=n;i++,u=f(u)){
    		node v=T;
    		for(int j=0;i+j<=n;j++,v=f(v))
    			ans=std::min(ans,dis(u,v)+k*(i+j));
    	}
    	printf("%.10Lf\n",ans);
    }
    int main(){
    	scanf("%d",&_);
    	while(_--)solve();
    	return 0;
    }
    
    • 1

    信息

    ID
    9258
    时间
    1000ms
    内存
    1024MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者