博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【XSY2921】yja 拉格朗日乘法
阅读量:4966 次
发布时间:2019-06-12

本文共 2367 字,大约阅读时间需要 7 分钟。

题目描述

  在平面上找 \(n\) 个点,要求这 \(n\) 个点离原点的距离分别是 \(r_1,r_2,\ldots,r_n\),最大化这 \(n\) 个点构成的土包的面积。这些点的顺序任意。

  \(n\leq 8\)

题解

  先枚举凸包上的点和顺序。

  不妨设 \(r_{n+1}=r_1\)

  面积为:\(\frac{1}{2}(r_1r_2\sin \theta_1+r_2r_3\sin \theta_2 + \cdots + r_nr_{n+1}\theta_n)\)

  那么问题就是最大化 \(r_1r_2\sin \theta_1+r_2r_3\sin \theta_2 + \cdots + r_nr_{n+1}\theta_n\),条件是 \(\theta_1+\theta_2+\cdots \theta_n=2\pi\)

  应用拉格朗日乘数法,有:

\[ \begin{cases} r_1r_2\cos\theta_1=r_2r_3\cos\theta_2=\cdots=r_nr_{n+1}\cos\theta_n&=\lambda\\ \theta_1+\theta_2+\cdots+\theta_n&=2\pi \end{cases} \]
  观察到 \(\theta_1,\theta_2,\ldots,\theta_n\) 关于 \(\lambda\)单调,所以可以二分 \(\lambda\) 算出 \(\theta_1,\theta_2,\ldots,\theta_n\)

代码

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;typedef long long ll;typedef unsigned long long ull;typedef pair
pii;typedef pair
pll;void sort(int &a,int &b){ if(a>b) swap(a,b);}void open(const char *s){#ifndef ONLINE_JUDGE char str[100]; sprintf(str,"%s.in",s); freopen(str,"r",stdin); sprintf(str,"%s.out",s); freopen(str,"w",stdout);#endif}int rd(){ int s=0,c; while((c=getchar())<'0'||c>'9'); do { s=s*10+c-'0'; } while((c=getchar())>='0'&&c<='9'); return s;}void put(int x){ if(!x) { putchar('0'); return; } static int c[20]; int t=0; while(x) { c[++t]=x%10; x/=10; } while(t) putchar(c[t--]+'0');}int upmin(int &a,int b){ if(b
a) { a=b; return 1; } return 0;}int n;const double eps=1e-9;const double pi=acos(-1);int a[10];double ans=0;auto gao=[](double x){return x<0?x+2*pi:x;};auto calc=[](double x){double s=0;for(int i=1;i<=n;i++)s+=gao(acos(x/a[i]/a[i+1]));return s;};void getans(){ sort(a+1,a+n+1); a[n+1]=a[1]; do { double s=0; double l=0,r=1e6; for(int i=1;i<=n;i++) r=min(r,(double)a[i]*a[i+1]); l=-r; if(calc(l)<2*pi||calc(r)>2*pi) continue; while(r-l>1e-5) { double mid=(l+r)/2; if(calc(mid)<2*pi) r=mid; else l=mid; } for(int i=1;i<=n;i++) s+=a[i]*a[i+1]*sin(acos(l/a[i]/a[i+1])); ans=max(ans,s); } while(next_permutation(a+2,a+n+1));}int r[10];int main(){ open("b"); int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&r[i]); if(n<=2) { printf("0\n"); return 0; } for(int i=1;i<1<
>(j-1))&1) a[++::n]=r[j]; if(::n>=3) getans(); } printf("%.10lf\n",ans/2); return 0;}

转载于:https://www.cnblogs.com/ywwyww/p/9073620.html

你可能感兴趣的文章
java zip 中文文件名乱码_java使用zip压缩中文文件名乱码的解决办法
查看>>
java if 用法详解_Java编程中的条件判断之if语句的用法详解
查看>>
java -f_java学习笔记(一)
查看>>
java 什么题目好做_用java做这些题目
查看>>
java中的合同打印_比较方法违反了Java 7中的一般合同
查看>>
php 位运算与权限,怎么在PHP中使用位运算对网站的权限进行管理
查看>>
php include效率,php include类文件超时
查看>>
matlab sin函数 fft,matlab的fft函数的使用教程
查看>>
wcdma下行如何解扩解扰 matlab,WCDMA技术基础.ppt
查看>>
MySQL date_format() 函数
查看>>
mysql 时间处理
查看>>
mysql adddate()函数
查看>>
mysql addtime() 函数
查看>>
mysql 根据日期时间查询数据
查看>>
mysql sin() 函数
查看>>
mysql upper() 函数
查看>>
mysql 子查询
查看>>
mysql 自联结
查看>>
mysql union 组合查询
查看>>
socket tcp
查看>>