標籤:

用C++暴力求出正方體中放置的最大正方形

前些天女朋友無聊刷知乎,刷到一個有趣的問題,拿這個來考我。本人數學不算好,但是儘力嘗試,算了許久都沒有算出來。但是作為一個計算機專業的大一寶寶,為什麼不能藉此機會體會一下暴力的美感呢。

原問題如下:

體積為1的正方體內,能放進的最大正方形面積是多少? @謝大大

首先,面積最大的正方形一定經過正方體的體心。

令最大的正方形為 M ,假設 M 不經過體心,則以體心為對稱中心做 M 的對稱圖形 M ,也在正方體內部。兩兩連接 MM 的四個頂點,得到一個柱體 MM ,此柱體的一個截面一定經過正方體體心。所以,面積最大的正方形中至少存在一個經過正方體體心,而由於正方形本身的對稱性,這個正方形的中心也必定是正方體的體心。

由於正方形的對角線相等並相互垂直平分,所以問題就轉化成 如何找到過正方體體心最長的一對相等的垂直平分線段。

然後,設其中一條對角線的一半為 OA ,在正方體上找到這一條線段:

則向量 overrightarrow{OA}(m,n,0.5) ,設過 O 點平面 alphaotoverrightarrow{OA} ,則 alphamx+ny+0.5z=0 ,接著我們找出 alpha 平面與 x=0.5,y=0.5,z=0.5 三個平面的交線。將 x=0.5 代入mx+ny+0.5z=0 ,得到 y=-frac{z+m}{2n}

然後我們要用代碼求出這個交線上離中心最遠的距離。

直接暴力即可。

#define STEP 0.001#define EPSILON 1e-5double dis(double a,double b,double c){ return sqrt(a*a+b*b+c*c);}double x_brane(double m,double n){ double re=0.0; double y; for(double z=-0.5;z<=0.5+EPSILON;z+=STEP) { y=-(z+m)/n/2.0; if(abs(y)<=0.5) { double t=dis(0.5,y,z); if(t>re) re=t; } } return re;}

同理求出 alpha 與其他兩個平面交線上離中心最遠的距離。

double y_brane(double m,double n){ double re=0.0; double z; for(double x=-0.5;x<=0.5+EPSILON;x+=STEP) { z=-2.0*m*x-n; if(abs(z)<=0.5) { double t=dis(x,0.5,z); if(t>re) re=t; } } return re;}double z_brane(double m,double n){ double re=0.0; double y; for(double x=-0.5;x<=0.5+EPSILON;x+=STEP) { y=-(m*x+0.25)/n; if(abs(y)<=0.5) { double t=dis(x,y,0.5); if(t>re) re=t; } } return re;}

得到三條交線離中心點最大的距離之後,在 left| OA 
ight| 與這個最大距離當中取最小值,得到的就是正方形對角線長度的一半,由此可求出正方形的面積。

然後對 m,n 進行枚舉,求出並記錄最大的情況即可。

int main(int argc, const char * argv[]) { double m=0,n=0; double ans=0; double ansm=0,ansn=0; for(m=0;m<=0.5+EPSILON;m+=STEP) for(n=0;n<=0.5+EPSILON;n+=STEP) { double this_egde=dis(m,n,0.5); double z=z_brane(m,n),x=x_brane(m,n),y=y_brane(m,n); printf("m=%.3lf, n=%.3lf, ",m,n); printf("x=%.3lf, y=%.3lf, z=%.3lf,",x,y,z); double max_edge=max(x,max(y,z)); printf(" s=%.3lf
",min(this_egde,max_edge)); if(ans { ans=min(this_egde,max_edge); ansm=m;ansn=n; } } cout<<ans<<" "<<(ans*ans)*2<<endl; printf("( %.3lf , %.3lf , %.3lf )
",ansm,ansn,0.5); return 0;}

最終結果:能放進的最大正方形面積為 1.125

各個頂點都在某條棱的1/4處,具體請看題圖。

本人學寫程序不久,水平有限,有錯誤或不足之處煩請各位大神指出,謝謝!


推薦閱讀:

Scrapy框架的使用抓取分析
windows7設置印表機共享
計算機發展史——史前計算機

TAG:C | 數學 | 計算機 |