BZOJ3775: 点和直线(计算几何+拉格朗日乘数法)
题面
题解
劲啊……
没有和\(Claris\)一样推,用了类似于\(Shinbokuow\)推已知点求最短直线的方法,结果\(WA\)了好几个小时,拿\(Claris\)代码拍了几个小时都没找到\(bug\)在哪儿,最后发现是我一个除法的地方忘记除数为\(0\)的情况了……甘霖娘……
公式恐惧症患者可以直接转去结论了
设直线为\(ax+by+c=0\),点为\((x,y)\),记\(d_i=a_i^2+b_i^2\),那么就是要我们最小化
f(x,y)
&=\sum {(a_ix+b_iy+c_i)^2\over d_i}\\
&=\sum {a_i^2x^2+b_i^2y^2+c_i^2+2a_ib_ixy+2a_ic_ix+2b_ic_iy\over d_i}
\end{aligned}
\]
以下为了方便,记\(A^2=\sum{a_i^2\over d_i}\),\(B^2,C^2\)同理,以及\(AB=\sum{a_ib_i\over d_i}\),\(BC,AC\)同理,那么原式可以表示成
\]
用拉格朗日乘数法对\(y\)求偏导数(这句话的意思大概就是,我们认为\(x\)是一个常数,那么对于每一个\(x=x_0\),\(y\)都会有一个极值点,而这个极值点就是它导数为\(0\)的点,所以我们把\(y\)看做变量求导)
\]
解得
\]
代入原式可以化为
\]
其中
\]
\]
\]
易知\(\alpha \geq 0\)(证明下面有)
不过这里其实还有一个尴尬的情况就是有可能\(B^2=0\),也就是说所有直线的\(b_i=0\),不过我们转过头去看会发现这种情况下\(y\)对\(f(x,y)\)完全没有影响,而且\(\alpha,\beta,\gamma\)的值分别就是\(A^2,2AC,C^2\)。所以这种情况其实并不会有影响
如果\(\alpha\neq 0\),我们要最小化\(f(x,y)\),同时还需要满足方程
\]
有解
代入根的判别式,可知需要满足
\]
\]
最小值显然了
如果\(\alpha=0\),则
\]
\(Claris\)说这种情况下答案就等于\(\gamma\)……然而我实在看不出为啥……我怎么感觉可以无限小呢……然而它要是变成负数显然不符合常理啊……有哪位鸽鸽知道为什么的么可以在下面留言哦qwq
然后就做完了
ps:关于\(\alpha\geq 0\)的证明
因为有
\]
首先显然\(B^2\geq 0\),如果\(B^2=0\),那么根据上面所说\(\alpha=A^2\geq 0\),所以假设\(B^2>0\),我们需要证明
\]
即
\]
代入原来的值
\]
这就是柯西不等式啊……显然成立
然后没有然后了
//minamoto
#include<bits/stdc++.h>
#define R register
#define inline __inline__ __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
int read(char *s){
R int len=0;R char ch;while(((ch=getc())>'9'||ch<'0'));
for(s[++len]=ch;(ch=getc())>='0'&&ch<='9';s[++len]=ch);
return s[len+1]='\0',len;
}
double readdb()
{
R double x=0,y=0.1,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(x=ch-'0';(ch=getc())>='0'&&ch<='9';x=x*10+ch-'0');
for(ch=='.'&&(ch=getc());ch>='0'&&ch<='9';x+=(ch-'0')*y,y*=0.1,ch=getc());
return x*f;
}
inline int getop(){R char ch;while((ch=getc())>'9'||ch<'0');return ch-'0';}
const int N=2e5+5;const double eps=1e-7;
inline int sgn(R double x){return x<-eps?-1:x>eps;}
struct node{
double aa,bb,cc,ab,bc,ac;int sz;
inline void ins(R double a,R double b,R double c,R double d){
++sz,aa+=a*a*d,bb+=b*b*d,cc+=c*c*d,ab+=a*b*d,ac+=a*c*d,bc+=b*c*d;
}
inline void del(R double a,R double b,R double c,R double d){
--sz,aa-=a*a*d,bb-=b*b*d,cc-=c*c*d,ab-=a*b*d,ac-=a*c*d,bc-=b*c*d;
}
double calc(){
if(!sz)return 0;
double invb=sgn(bb)?1.0/bb:0;
double a=aa-ab*ab*invb,b=2*ac-2*ab*bc*invb,c=cc-bc*bc*invb;
return !sgn(a)?c:c-b*b*0.25/a;
}
}q;
struct Line{
double a,b,c,d;
inline Line(){}
inline Line(R double x,R double y,R double xx,R double yy){
!sgn(x-xx)?(a=1,b=0,c=-x):(a=(yy-y)/(xx-x),b=-1,c=y-a*x);
d=1.0/(a*a+b*b);
}
}L[N];
int top,op,i;double x,y,xx,yy,res;
int main(){
// freopen("testdata.in","r",stdin);
// freopen("testdata.out","w",stdout);
for(int T=read();T;--T){
op=getop();
switch(op){
case 0:{
x=readdb(),y=readdb(),xx=readdb(),yy=readdb();
L[++top]=Line(x,y,xx,yy),q.ins(L[top].a,L[top].b,L[top].c,L[top].d);
break;
}
case 1:{
i=read(),q.del(L[i].a,L[i].b,L[i].c,L[i].d);
break;
}
case 2:{
res=q.calc();
if(res<1e-3&&res>-1e-3)res=0;
printf("%.2lf\n",res);
break;
}
}
}
return 0;
}
BZOJ3775: 点和直线(计算几何+拉格朗日乘数法)的更多相关文章
- CodeChef TWOROADS(计算几何+拉格朗日乘数法)
题面 传送门 简要题意:给出\(n\)个点,请求出两条直线,并最小化每个点到离它最近的那条直线的距离的平方和,\(n\leq 100\) orz Shinbokuow 前置芝士 给出\(n\)个点,请 ...
- ML(附录4)——拉格朗日乘数法
基本的拉格朗日乘子法(又称为拉格朗日乘数法),就是求函数 f(x1,x2,...) 在 g(x1,x2,...)=C 的约束条件下的极值的方法.其主要思想是引入一个新的参数 λ (即拉格朗日乘子),将 ...
- [Math & Algorithm] 拉格朗日乘数法
拉格朗日乘数法(Lagrange Multiplier Method)之前听数学老师授课的时候就是一知半解,现在越发感觉拉格朗日乘数法应用的广泛性,所以特意抽时间学习了麻省理工学院的在线数学课程.新学 ...
- 《University Calculus》-chaper12-多元函数-拉格朗日乘数法
求解条件极值的方法:拉格朗日乘数法 基于对多元函数极值方法的了解,再具体的问题中我们发现这样一个问题,在求解f(x,y,z)的极值的时候,我们需要极值点落在g(x,y,z)上这种对极值点有约束条件,通 ...
- bzoj2876 [NOI2012]骑行川藏(拉格朗日乘数法)
题目描述 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因此在每天的骑行 ...
- BZOJ2876 [Noi2012]骑行川藏 【拉格朗日乘数法】
题目链接 BZOJ 题解 拉格朗日乘数法 拉格朗日乘数法用以求多元函数在约束下的极值 我们设多元函数\(f(x_1,x_2,x_3,\dots,x_n)\) 以及限制\(g(x_1,x_2,x_3,\ ...
- 拉格朗日乘数法 和 KTT条件
预备知识 令 \(X\) 表示一个变量组(向量) \((x_1, x_2, \cdots, x_n)\) 考虑一个处处可导的函数 \(f(X)\), 为了方便描述, 这里以二元函数为例 对于微分, 考 ...
- CodeForces - 813C The Tag Game(拉格朗日乘数法,限制条件求最值)
[传送门]http://codeforces.com/problemset/problem/813/C [题意]给定整数a,b,c,s,求使得 xa yb zc值最大的实数 x,y,z , 其中x ...
- Wannafly模拟赛2 B river(拉格朗日乘数法)
题目 https://www.nowcoder.com/acm/contest/4/B题意 有n条南北流向的河并列排着,水流速度是v,现在你需要从西岸游到东岸,总共T个时间,你的游泳速度是u,问东岸的 ...
随机推荐
- EXP-00056:遇到oracle错误12154
执行命令如下: 引用 exp user/pwd@dbname file=d:text.dmp owner=(user) 碰到了错误: 引用 EXP-00056:遇到oracle错误12154 ORA- ...
- Golang之Mysql操作
话说当年武大郎对着电脑一顿噼里啪啦,,,对mysql增删改查 增加insert package main import ( "fmt" "github.com/jmoir ...
- myschool 1204
http://oj.jxust.edu.cn/problem.php?id=1274 #include <iostream> #include <set> using name ...
- vc到vs2015消息函数
afx_msg LRESULT OnMyIconNotify(WPARAM wParam,LPARAM lParam); vc6 可以是void vs2015不可以 ON_MESSAGE(MYWM_ ...
- 五个步骤搞定敏捷UX设计
互联网产品发展的速度越来越快,人们对于产品的要求也在不断的升级,这直接地导致了用户体验设计的重要性不断提升.与此同时,过去的流程冗长的设计开发模式已经不能够满足快速迭代的需要.<敏捷宣言> ...
- mathematica里面清除全部变量
基本在一个独立代码开始都写: Clear["Global`*"] (*Clear all variables*) 就可以了
- SQLInjection 靶场配置
对于渗透,太小型的网站没有太大价值,而大型网站(比如各种电商平台)对于代码审计往往非常严格,新手基本找不到漏洞,而一些比较容易搞掉的站点(政府.gov.各种教育网站.edu或者很多商业中型站点)渗透又 ...
- 解决启动nginx时报80端口被占用的问题
如何解决启动nginx时报80端口被占用 最近公司的的一个服务器上需要部署多个项目,但80端口只有一个,所有只有使用Nginx来代理,当访问域名时就可以自动 转到IP:端口号,而不需要在域名后面加端口 ...
- 2018.09.02 bzoj1296: [SCOI2009]粉刷匠(dp套dp)
传送门 dp好题. 先推出对于每一行花费k次能最多粉刷的格子数. 然后再推前i行花费k次能最多粉刷的格子数. 代码: #include<bits/stdc++.h> #define N 5 ...
- Mysql字符串字段判断是否包含某个字符串的3种方法[转载]
方法一: SELECT * FROM users WHERE emails like "%b@email.com%"; 方法二: 利用mysql字符串函数 find_in_set( ...