• 无题的题 & 模拟退火...


    题意:

      给你不超过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
    ",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
    "); 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
    ",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
    ",ans);
    	}
    }
    
  • 相关阅读:
    面向对象 (11)求交并集 判断字符形式
    软件工程 课程总结
    面向对象 (10)正则判邮箱
    面向对象 (9)计算时间差 找随机数范围内规律
    面向对象 (8)字符串出现字符个数统计 字母组成回文串判定
    面向对象 (7)中介买房 平均数异常处理
    面向对象 (6)买房付首款
    第16周作业
    第15周作业
    迟到的第14周作业
  • 原文地址:https://www.cnblogs.com/YCuangWhen/p/5365514.html
Copyright © 2020-2023  润新知