无题的题 & 模拟退火...
题意:
给你不超过8条一端在圆心的半径,求他们组成的凸包的最大面积.
SOL:
正解怎么搞啊不会啊...然后昨天毛爷爷刚讲过模拟退火...那么就打一个吧...
然后就T了,不过三角形的部分分妥妥的...
然后在自信的协助下被他改了改参数然后过了九个点...(对着数据调参也是醉了...
剩下一个点感觉没法搞啊QAQ...差太多了...感觉退完火爬爬山应该会很兹瓷...
90分code:
/*========================================================================== # Last modified: # Filename: .cpp # Description: ==========================================================================*/ #define me AcrossTheSky #include <cstdio> #include <cmath> #include <ctime> #include <string> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <set> #include <map> #include <stack> #include <queue> #include <vector> #define lowbit(x) (x)&(-x) #define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++) #define FORP(i,a,b) for(int i=(a);i<=(b);i++) #define FORM(i,a,b) for(int i=(a);i>=(b);i--) #define ls(a,b) (((a)+(b)) << 1) #define rs(a,b) (((a)+(b)) >> 1) #define getlc(a) ch[(a)][0] #define getrc(a) ch[(a)][1] #define maxn 10 #define maxm 100000 #define limm 1e-6 #define pi acos(-1) #define _e 2.718281828459 #define INF 1070000000 using namespace std; typedef long long ll; typedef unsigned long long ull; template<class T> inline void read(T& num) { bool start=false,neg=false; char c; num=0; while((c=getchar())!=EOF) { if(c=='-') start=neg=true; else if(c>='0' && c<='9') { start=true; num=num*10+c-'0'; } else if(start) break; } if(neg) num=-num; } /*==================split line==================*/ int a[maxn],temp[maxn],tmp[maxn]; double angle[maxn]; int n; double ans=0; bool vis[maxn]; set<int> s; int cmp(int x,int y){return x>y;} double getang(double x){ return x/180*pi; } double calc(int ord,double ang,int m){ return temp[ord]*temp[ord%m+1]*sin(getang(ang))/2; } int getposb(double c,double b){ double tttt=exp(c/b); return tttt; } void work(int m){ double aaa=360.0/m; double sum=0; FORP(i,1,m) { angle[i]=aaa; sum+=calc(i,angle[i],m); } //angle[m]=360-aaa; //sum+=calc(m,angle[m],m); double maxx=sum; //ans=max(ans,sum); double T=100; if (n < 4) T = 1000; while (fabs(T-0)>1e-5){ if (maxx < 94*ans/100) return; int pos=rand()%m+1,next=pos%m+1; double ttemp=calc(pos,angle[pos],m)+calc(next,angle[next],m); ll cap=trunc(max(angle[pos],angle[next])*100000000/T); double change=(rand()%cap)*T/100000000; double dx,dy; if (angle[pos]-change<0) dx=angle[pos]+change,dy=angle[next]-change; else dx=angle[pos]-change,dy=angle[next]+change; double delta=calc(pos,dx,m)+calc(next,dy,m)-ttemp; if (delta>0){ sum+=delta; angle[pos]=dx,angle[next]=dy; } else{ double posb=getposb(delta,ans*T); int xxx=10000000/trunc(T); int rp=rand()%xxx; if ((double)rp*T/100000000.0<posb) { sum+=delta; angle[pos]=dx,angle[next]=dy; } } if (sum>ans) { //FORP(i,1,m) printf("%d ",temp[i]); //cout << endl; //FORP(i,1,m) printf("%lf ",angle[i]); //cout << endl; //printf("%lf\n",sum); ans=sum; } maxx=max(maxx,sum); if (n >= 4) T*=0.89; else T *= 0.999; } if (sum>ans) ans=sum; } int fpow(int s,int m){ int ret=1; for (;m;m>>=1,s=s*s) if (m&1) ret*=s; return ret; } void dfs(int x,int m,int tot){ if (x==m+1) { work(m);work(m); work(m);work(m); return; } FORP(i,1,n) if (!vis[i]) { vis[i]=true; temp[x]=a[i]; dfs(x+1,m,tot*10+i); vis[i]=false; } } int main(){ srand(time(0)); freopen("yist.in","r",stdin); freopen("yist.out","w",stdout); read(n); bool flag=true; if (n==2) {printf("0\n"); return 0;} FORP(i,1,n) read(a[i]); FORP(i,1,n) { if (i>1 & a[i]!=a[i-1]) flag=false; } if (flag){ if (n==3) printf("%.8lf\n",a[1]*sqrt(3)*(a[1]+a[1]/2.0)/2.0); else printf("%.8lf",(double)a[1]*a[1]*sin(2*pi/n)*n/2.0); } else{ if (n==3){ FORP(i,1,n) temp[i]=a[i]; dfs(1,n,0); } else{ FORP(i,3,n-1){ memset(vis,false,sizeof(vis)); //s.clear(); dfs(1,i,0); } memset(vis,false,sizeof(vis)); s.clear(); temp[1]=1; vis[1]=1; dfs(2,n,0); } printf("%.10lf\n",ans); } }
Sometimes it s the very people who no one imagines anything of. who do the things that no one can imagine.