嘗試用C語言解題
BUG fix :
W:槽的SciTE有點小問題,因為設定檔是從Y:複製來的,所以需要重新定義TinyC的位置。
只要修改cpp.properties的路徑就可以了。
Nutcracker Solution :
上學期的Nutcracker網誌內容。
之前的python題目,稍微研究一下後轉成C語言。
不過如果直接運行會跑很久。但是這裡可以練習一下小型演算法的模式。
先做了兩個程式,不過第一是介面而已,第二個才是主要架構。
撰寫的途中使用Solvespace研究,由於數學邏輯不太好,很多幾何的東西沒那麼直觀。
有時候會偷吃步測試一些解法。
第二支程式是從python的範例改來的,不過後來做了很多變化,只有解最小路徑最大角度。
演算法概念:
途中查了很多數學公式,無奈常常打錯又不知道正確性,重複試了很多次才成功。
#include#include int k=40; int h=10; int a=40; int b=80; double r=10; double pi=M_PI; int num=1000; int main() { double deg =pi/180; for (int j=45*num; j<=180*num; j++){ double num0=num; double th=j/num0*deg; double x1=a*cos(th); double y1=a*sin(th); double x2=x1+sqrt(b*b-y1*y1); double m=tan(th); double r1=abs((x2-x1)*(h-y1)-(0-y1)*(k/2-x1))/sqrt(y1*y1+(x2-x1)*(x2-x1)); printf("%g\n", (int)(j/num0*100000+.5)/100000.); if(r1<=r){ printf("(%f,%f) (%f,0)\n%f\n%f r=%f\nm=%f\n", x1, y1, x2, th/deg, r, r1, m); break; } } return 0; }
第二支程式的最後成果。
最後精確度還是沒有很高,不知道問題出在哪裡。
第一支程式是剛開始寫輸入端介面,供使用者輸入自訂參數,後來再把第二支程式的模型搬回來用,並另外寫一個解最大路徑和最小角度的程式,所有例外狀況也是在這裡排除。
後來還不知道怎麼讓副程式傳回double或其他浮點數,查一下才知道要在開始前宣告一次。
#include#include int a, b, k, h, r, lim; double o, wp, thmin, thmax; double pi=M_PI; int num=1000; double solve_minpath(int, int, int, int, int); double solve_maxangle(int, int, int, int, int); double solve_maxpath(int, int, int, int); double solve_minangle(int, int, int, int); int main() { scanf("%d,%d,%d,%d,%d,%d", &a, &b, &k, &h, &r, &lim); //強制正值 a=abs(a); b=abs(b); h=abs(h); k=abs(k); r=abs(r); lim=abs(lim); printf("\n---\n"); printf("Used pi= %f\n", pi); printf("---\n"); printf("Connecting Rod:\n"); printf("a= %d b= %d\n", a, b); printf("Rod radius= %d\n", r); printf("Rod width= %d\n", r*2); printf("Space Usage:\n"); printf("h= %d k= %d\n", h, k); printf("Work Path= %d\n", lim); printf("---\n\n"); //相關參數代入副程式解題 o=solve_minpath(k, h, a, b, r); wp=solve_maxpath(lim, a, b, r)-o; thmin=solve_minangle(lim, a, b, r); thmax=solve_maxangle(k, h, a, b, r); if(a*b*lim==0){ printf("---ERRO---\nSome value can't be zero.\n"); return 1; } else{ if(o+r>lim){ printf("---ERRO---\nSpace is not enough.\n"); return 2; } else{ printf("\n---\n---Result---\n"); printf("Distance:\n"); printf("Offset distance:\n"); printf("o= %f\n", o); printf("Work distance:\n"); printf("wp= %f\n", wp); printf("Angle(Degree):\n"); printf("min= %f max= %f\n---\n", thmin, thmax); return 0; } } } double solve_minpath(int k, int h, int a, int b, int r) { double deg =pi/180; for (int j=45*num; 180*num>=j; j++){ double num0=num; double th=j/num0*deg; double x1=a*cos(th); double y1=a*sin(th); double x2=x1+sqrt(b*b-y1*y1); double m=tan(th); double r1=abs((x2-x1)*(h-y1)-(0-y1)*(k/2-x1))/sqrt(y1*y1+(x2-x1)*(x2-x1)); if(r>=r1){ printf("(%f,%f) (%f,0)\n%f\n%f r=%f\nm=%f\n", x1, y1, x2, th/deg, r, r1, m); return x2; break; } } return 0; } double solve_maxangle(int k, int h, int a, int b, int r) { double deg =pi/180; for (int j=45*num; 180*num>=j; j++){ double num0=num; double th=j/num0*deg; double x1=a*cos(th); double y1=a*sin(th); double x2=x1+sqrt(b*b-y1*y1); double m=tan(th); double r1=abs((x2-x1)*(h-y1)-(0-y1)*(k/2-x1))/sqrt(y1*y1+(x2-x1)*(x2-x1)); if(r>=r1){ printf("(%f,%f) (%f,0)\n%f\n%f r=%f\nm=%f\n", x1, y1, x2, th/deg, r, r1, m); return th/deg; break; } } return 0; } double solve_maxpath(int lim, int a, int b, int r) { double n; double th; if (lim>a+b+r){ n=a+b; th=0; } else{ n=lim-r; th=acos((a*a+n*n-b*b)/2*a*n); } return n; } double solve_minangle(int lim, int a, int b, int r) { double n; double th; if (lim>a+b+r){ n=a+b; th=0; } else{ n=lim-r; th=acos((a*a+n*n-b*b)/(2*a*n)); } return th; }
最後執行的結果:
剛開始還以為是用公式推導座標點的結果,後來回去看網誌才知道用演算法計算。電腦演算時如果一邊列出結果,會拖慢速度,所以在最後的程式碼中只留檢查用的結果。
後來也有上網看其他人使用基因演算法的案例,未能完全了解,還有很多要學習的地方。這次解題複習了一些C語言的概念,希望在往後利用上能夠駕輕就熟。
Comments
comments powered by Disqus