首页 > 其他分享 >题解 SP4586 Texas Trip

题解 SP4586 Texas Trip

时间:2023-09-10 12:00:17浏览次数:60  
标签:SP4586 int 题解 db double theta inf Trip define

首先题目翻译是有问题的,求的不是矩形而是最小的正方形

Solution

先考虑一下若正方形的边都只能平行于坐标轴怎么做:找到 \(x,y\) 方向的坐标最值,那么答案就是 \(\max^2\{X_{\max}-X_{\min},Y_{\max}-Y_{\min}\}\)。
接下来,若正方形可以是斜着的,我们只需把坐标轴旋转,然后同样找出旋转后的坐标最值即可。而坐标的变换即为 \((x,y)\rightarrow(x\cos\theta-y\sin\theta,x\sin\theta+y\cos\theta)\)。那么现在的问题就是找到一个合适的旋转角度使得答案最小。
由于此题精度要求较高,所以暴力是行不通的。我看到提交中有一些用了三分,但实际上很明显边长随角度变化不是一个单峰函数,三分能过只是因为数据水了。
那么对于这样的多峰函数,用模拟退火找出最值即可。

Code

#include<bits/stdc++.h>
using namespace std;
#define db double
const int N=33;
const db pi=acos(-1),inf=1e18,eps=1e-15;
int n;
pair<db,db>p[N];
#define fi first
#define se second
#define sqr(x) ((x)*(x))
mt19937 rnd(time(0));
db calc(db a){
	db xmn=inf,xmx=-inf,ymn=inf,ymx=-inf;
	for(int i=1;i<=n;i++){
		db x=p[i].fi,y=p[i].se;
		db cx=x*cos(a)-y*sin(a),
		   cy=x*sin(a)+y*cos(a);
		xmn=min(xmn,cx);xmx=max(xmx,cx);
		ymn=min(ymn,cy);ymx=max(ymx,cy);
	}
	return max(xmx-xmn,ymx-ymn);
}
db ans,bk;
void SA(){
    double k=bk,t=3000;
    while(t>eps){
        double kk=k+t*((int)rnd()-INT_MAX);
        double now=calc(kk/(db)UINT_MAX*pi);
        double dt=now-ans;
        if(dt<0)bk=k=kk,ans=now;
        else if(exp(-dt/t)*UINT_MAX>rnd())k=kk;
        t*=0.996;
    }
}

int main(){
	int T;scanf("%d",&T);
	for(int t=1;t<=T;t++){
		scanf("%d",&n);
		for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].fi,&p[i].se);
		bk=rnd();ans=inf;
		for(int i=1;i<=8;i++)SA();
		printf("%.2lf\n",ans*ans);
	}
	return 0;
}

标签:SP4586,int,题解,db,double,theta,inf,Trip,define
From: https://www.cnblogs.com/aday526/p/solution-sp4586.html

相关文章

  • 题解 P8389【[COI2021] Izvanzemaljci】
    (本题解的所有图片使用GeometryWidget进行绘制)(一)\(K=1\)情况\(K=1\)是平凡的。(二)\(K=2\)情况显然,对于平面内的两个不交正方形,存在至少一条平行于坐标轴的直线将它们划分到两侧。以直线平行于\(y\)轴为例。考虑按\(x\)轴正方向扫描线。先将点按照\(x\)坐标排序,维......
  • cnpm : 无法加载文件 \npm\cnpm.ps1,因为在此系统上禁止运行脚本。 问题解决
    很久没有弄前端VUE了。最近用到的vscode进行前端摸索。在用NPM的时候,发现有点慢,于是切换到了cnpm。在使用cnpm进行运行的时候报错了。“cnpm:无法加载文件C:\Users\Administrator\AppData\Roaming\npm\cnpm.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅https:/go.mi......
  • 【题解】三连击
    [NOIP1998普及组]三连击思路想一想桶得到三个数之后把每一位依次存入桶然后遍历这个桶,看哪一位为\(0\)代码//语言:C++#include<iostream>#include<cstring>//memsetusingnamespacestd;intmain(){ for(inti=123;i<=987/3;i++) { inta=i,b=2*i,c=3*i; i......
  • P3533 [POI2012] RAN-Rendezvous 题解
    P3533[POI2012]RAN-Rendezvous题目大意:给定外向树森林,每次给定两个起始点,求两个点沿边移动最少步数相遇。\(n\)个点,\(n\)条边,并且每个点有唯一的出边,显然构成了多棵基环树,对于每个基环树分别处理:找出环上的点,因为要求支持求出任意两点距离,前缀和一下即可。对于询问,如果在两......
  • vncviewer黑屏问题解决
    如果不知道kill多少值,可通过ps-ef|grepvnc进行查看1.先kill掉现在的vnc端口进程(假设端口是1):比如:vncserver-kill:12.打开启动文件xstartup:vim~/.vnc/xstartup3.修改其中的内容如下:#!/bin/shexportXKL_XMODMAP_DISABLE=1unsetSESSION_MANAGERunsetDBUS_SESSION_BUS_AD......
  • CF1570D 题解
    思路分析前言题解区好似没有用哈希的啊。发现大家都在用map来存是否出现过数字,但是需要注意的是,map的单次查询时间复杂度是\(\mathcalO(\logn)\)的,对于大规模的数据就很可能会TLE。所以,我们可以使用哈希的方法来判断数字是否出现过。浅谈哈希哈希,是通过哈希函数将数......
  • 【题解】Educational Codeforces Round 143(CF1795)
    A.TwoTowers题目描述:有\(a,b\)两座由红蓝色方块垒成的塔,其中\(a\)的高度为\(n\);\(b\)的高度为\(m\),用R代表红色;用B代表蓝色。你可以多次把其中一座顶端的方块移到另一座的顶端(可以不移动)。问有没有一种方法可以使两座塔中均没有连续的同颜色方块。题目分析:可以......
  • Codeforces Round 827 (Div. 4) C. Stripes
    在一个\(8\times8\)的网格上,一开始无色。每次一整行或一整列地染色,后染的颜色会覆盖前染的颜色。染色方式有两种,一种是横着染\(R\)色,一种是竖着染\(B\)色。给出最终染色的网格,问最后染的色是哪种。对每行开\(R\)计数器、每列开\(B\)计数器。遍历行、列,如果计数器的......
  • UVA202 题解
    思路分析前言又是一道小模拟题,不过细节巨多,可以用来锻炼自己的代码能力。解法本题实际上就是模拟长除法的计算过程,其中每一步除法时都有被除数及其余数,当被除数出现重复时就表示出现循环节了。所以需要记录每一次的被除数及其在循环小数中的位置,需要判断当除数不够除,每一次补......
  • 题解 [CQOI2009] 中位数
    题目链接要想使得数字\(x\)是中位数,就必须选出\(k\)个小于\(x\)的数和\(k\)个大于\(x\)的数。我们考虑对数字附上特殊值,小于\(x\)的数赋值为\(-1\),大于\(x\)的数赋值为\(1\),\(x\)则赋值为\(0\),那么若一段包含\(x\)的连续序列的和等于\(0\),就可以说明这段连......