题意:
给两个相关区域,但是不同比例的地图,第一个是左下角(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);
}