A - Renzo and the lost artifact Gym - 101064A(模拟退火 求两个正方形的重合点)

题意:

给两个相关区域,但是不同比例的地图,第一个是左下角(0,0),右上角(W,H)。
第二个是比例比较小的地图,分别给出左下、右下、右上、左上四个点。
第二张地图可能旋转甚至翻转。

在这里插入图片描述

在平面上有一个点,在两张地图上的位置相同。求这个点。

解析:

如何不能旋转直接就可以求出来
在这里插入图片描述
旋转的话就模拟退火,退火的点P在大地图上移动,然后求出在小地图上的映射点P2。答案一定是 D i s ( P , P 2 ) = 0 Dis(P,P2)=0 Dis(P,P2)=0。所以退火点移动的标准就是新点的 D i s ( P , P 2 ) Dis(P,P2) Dis(P,P2)是否比原先的 D i s ( P , P 2 ) Dis(P,P2) Dis(P,P2)小。

代码:

模拟退火板子级别的题目

/*
 *  Author : Jk_Chen
 *    Date : 2021-03-27-13.51.34
 */
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double LD;
typedef long double F;
typedef pair<int, int> pill;
#define rep(i, a, b) for (int i = (int)(a); i <= (int)(b); i++)
#define per(i, a, b) for (int i = (int)(a); i >= (int)(b); i--)
#define mmm(a, b) memset(a, b, sizeof(a))
#define pb push_back
#define fi first
#define se second
void test()
{
    cerr << "\n";
}
template <typename T, typename... Args>
void test(T x, Args... args)
{
    cerr << "> " << x << " ";
    test(args...);
}
const LL mod = 1e9 + 7;
const int maxn = 200 + 9;
const int maxm = 5000 + 9;
const int inf = 0x3f3f3f3f;
LL rd()
{
    LL ans = 0;
    char last = ' ', ch = getchar();
    while (!(ch >= '0' && ch <= '9'))
        last = ch, ch = getchar();
    while (ch >= '0' && ch <= '9')
        ans = ans * 10 + ch - '0', ch = getchar();
    if (last == '-')
        ans = -ans;
    return ans;
}
#define rd rd()
LD rdld(){
    double tmp;
    scanf("%lf", &tmp);
    return (LD)tmp;
}
/*_________________________________________________________begin*/
const F eps = 1e-6;
struct point{
    F x,y;
    point(){}
    point(F x,F y):x(x),y(y){}
};
typedef point Vector;
typedef point Point;
Vector operator + (Vector a, Vector b){//向量加法
    return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (Vector a, Vector b){//向量减法
    return Vector(a.x - b.x, a.y - b.y);
}
Vector operator * (Vector a, F p){//向量数乘
    return Vector(a.x*p, a.y*p);
}
Vector operator / (Vector a, F p){//向量数除
    return Vector(a.x / p, a.y / p);
}
int dcmp(F x){//精度三态函数(>0,<0,=0)
    if (fabs(x) < eps)return 0;
    else if (x > 0)return 1;
    return -1;
}
bool operator == (const Point &a, const Point &b){//向量相等
    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
F Dot(Vector a, Vector b){//内积
    return a.x*b.x + a.y*b.y;
}
F Length(Vector a){//模
    return sqrt(Dot(a, a));
}
F Cross(Vector a, Vector b){//外积
    return a.x*b.y - a.y*b.x;
}
F Angle(Vector a, Vector b)
{ //夹角,弧度制
    F d2 = Dot(a, b) / Length(a) / Length(b);
    if (d2 < -1)
        d2 = -1;
    if (d2 > 1)
        d2 = 1;
    F ang = acos(d2);
    if (Cross(a, b) < 0)
    {
        ang = -ang;
    }
    return ang;
}
Vector Rotate(Vector a, F rad){//逆时针旋转
    return Vector(a.x*cos(rad) - a.y*sin(rad), a.x*sin(rad) + a.y*cos(rad));
}
Vector RotateTogether(Vector A1, Vector A2, Vector C){ //A1旋转到A2后,C应该旋转到哪里
    F ang = Angle(A1, A2);
    return Rotate(C, ang);
}
F Distance(Point a, Point b){//两点间距离
    return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
/*_________________________________________________________math*/

LD T = 100, delta = 0.98;

LD H = rdld(), W = rdld();
point p[4],P;
const point di[] = {{1, 0}, {0, 1}, {0, -1}, {-1, 0}};

point Get2(point P){
    return p[0] + (p[1] - p[0]) * (P.x / W) + (p[2] - p[1]) * (P.y / H);
}

void SA(){
    P = p[0];
    double t = T, dis = 1e99;
    while(t > eps) {
        bool f = 1;
        while(f) {
            f = 0;
            for(int i = 0; i < 4; i++) {
                point toP = P + di[i] * t;
                point toP2 = Get2(toP);
                LD disnow = Distance(toP, toP2);
                if(dcmp(disnow - dis) < 0){
                    dis = disnow;
                    P = toP;
                    f = 1;
                }
            }
        }
        t *= delta;
    }
}

int main(){
    rep(i, 0, 3) p[i].x = rdld(), p[i].y = rdld();
    SA();
    printf("%.10f %.10f\n", (double)P.x, (double)P.y);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值