拉格朗日乘数法

157 篇文章 0 订阅
68 篇文章 0 订阅

对于只有一个自变量的单峰函数我们可以三分解决。

当然我们也可以求导数然后二分也行(只要你导得出来)

但是对于多个自变量,莫非三分套三分?

套两三个或许可以。

但是我们可以用偏导一次解方程(其实也是二分答案)求出最值(前提是只有一个极值点且你能求偏导)

这就是拉格朗日乘数法。

具体来讲就是你需要求最值的函数是一个山峰,

这个山峰的高度即为函数值,我们可以画出等高线(所以地理在某种程度上算理科)

而这个函数中自变量之间的限制关系画出了一条登山路线,你求的最值即是在路线上的最高点。

你的路线是一条平滑的可求偏导的曲线(不然用什么导数),

然后你仔细想一下,你路线上的最高点所属的等高线(也应该是一条平滑可求偏导的曲线)应该是和你的路线相切的!

然后。。。。。。度娘吧。


在平面上找 n 个点, 要求这 n 个点离原点的距离分别为 r1; r2; :::; rn. 最大化这 n 个点构成的

凸包面积, 凸包上的点的顺序任意

n<=8


枚举点的顺序(可能有一些点用不着)然后就是求关于n个夹角的函数的最值。

这个很好求导吧。

lambda = r1 * r2 * cos sita1 = r2 * r3 * cos sita2 ..........

sita1 + .....sita n =2 PI

lambda 和sita之间有单调性所以可以二分


code:

/*
Lagrange Multiplier
F(x,y,Lambda) = f(x,y) + λ* φ( x,y ) 

*/
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<iomanip>
#include<iostream> 
#include<cmath>
#define maxn 10
#define eps 1e-12
#define PI 3.1415926535897932384626433832795
#define double long double
using namespace std;

int n;
double l[maxn];

int seq[maxn],vis[maxn];

double ans=0;

bool check2(double lambda,int n)
{
	double sita=0,tmp;
	for(int i=1;i<=n;i++)
	{
		tmp=acos(lambda / l[seq[i]] / l[seq[i%n+1]]);
		sita+=tmp;
	}
	return sita>=2*PI;
}

void check(int n)
{
	double Min=0x3f3f3f3f;
	for(int i=1;i<=n;i++) Min=min(Min,l[seq[i]]*l[seq[i%n+1]]);
	double L=-Min,R=Min,Mid;
	for(;L<R-eps;)
	{
		Mid=(L+R)*0.5;
		if(check2(Mid,n)) L=Mid;
		else R=Mid;
	} 
	if(!check2(L,n)) return;
	double tmp,ret=0;
	for(int i=1;i<=n;i++)
	{
		tmp=acos(L / l[seq[i]] / l[seq[i%n+1]]);
		ret+=l[seq[i]]*l[seq[i%n+1]]*sin(tmp)*0.5;
	} 
	ans=max(ans,ret);
}

void dfs(int k)
{
	if(k>1) 
		check(k-1);
	for(int i=1;i<=n;i++)
		if(!vis[i])
		{
			vis[seq[k]=i]=1;	
			dfs(k+1);
			vis[i]=0;
		}
}

int main()
{
	
	freopen("yja.in","r",stdin);
	
	scanf("%d",&n);
	for(int i=1;i<=n;i++) cin>>l[i];
	dfs(1);
	cout<<setprecision(20)<<ans;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值