教學班級:005(週三上午三四節)git
項目地址:https://github.com/a458269373/software_firstgithub
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | ||
· Estimate | · 估計這個任務須要多少時間 | 10 | 10 |
Development | 開發 | ||
· Analysis | · 需求分析 (包括學習新技術) | 100 | 150 |
· Design Spec | · 生成設計文檔 | 50 | 60 |
· Design Review | · 設計複審 (和同事審覈設計文檔) | 15 | 15 |
· Coding Standard | · 代碼規範 (爲目前的開發制定合適的規範) | 15 | 15 |
· Design | · 具體設計 | 60 | 80 |
· Coding | · 具體編碼 | 30 | 30 |
· Code Review | · 代碼複審 | 40 | 40 |
· Test | · 測試(自我測試,修改代碼,提交修改) | 200 | 250 |
Reporting | 報告 | 100 | 100 |
· Test Report | · 測試報告 | 30 | 30 |
· Size Measurement | · 計算工做量 | 20 | 20 |
· Postmortem & Process Improvement Plan | · 過後總結, 並提出過程改進計劃 | 50 | 60 |
- | 合計 | 720 | 860 |
本次做業只完成了求直線交點部分:算法
直線方程使用\(ax+by+c=0\)的形式,能夠很好的規避斜率問題,進而減小分類討論。函數
能夠很容易的獲得,直線給出兩點\((x1,y1)、(x2,y2)\),則直線方程中的參數能夠表示爲:性能
\(\begin{cases} a = y1-y2\\ b = x1 - x2\\c = y2 * x1 - y1 * x2\end{cases}\)單元測試
求兩直線相交時,直線方程爲\(a1x+b1y+c1=0\)、\(a2x+b2y+c2=0\),根據公式推導可得:學習
\(\begin{cases} x = (b1 * c2 - b2 * c1)/(a1 * b2 - a2 *b1)\\ y = (a2 *c1 - a1 * c2 )/(a1 * b2 - a2 *b1)\\\end{cases}\)測試
最終,去重後交點個數即爲所求。優化
本次做業我使用了兩種思路:編碼
一、有兩個點及以上在新直線上,則新直線必於以前讀入的某條直線重合,因此能夠直接放棄新直線。
二、只有一點在新直線上,則找到通過該點的全部直線,新直線與這些直線不會產生新的交點,省去了一批重複運算。
三、無交點在新直線上,則新直線計算與所有已有直線的焦點。
性能改進:經過查閱資料瞭解到,直線求交點問題沒法逃出遍歷的牢籠,只能在去重這一點上作出優化。
struct point { double x; // 橫座標 double y;//縱座標 vector<int> belong;//直線下標 }; class line { public: //ax+by+c=0 long long a = 0; long long b = 0; long long c = 0; static void calInteract(line l1, line l2); line(long long x1, long long y1, long long x2, long long y2); }; //main 邏輯 line templine(x1, y1, x2, y2); if(addInteract(templine,lineNum) < 2){ //只有小於2,新直線纔不重合 for (int j = 0; j < lineNum; j++) { if(find(InteractLine.begin(),InteractLine.end() == InteractLine.begin()){ //去重邏輯,兩直線不相交於已計入的焦點。 line::calInteract(templine, lines[j]); } } lines.push_back(templine); lineNum++; }
一個類line,一個結構體point。
使用pair<double,double>來表示每個點,使用map的key的不可重複性來去重。
vector<line> lines; map<pair<double, double>,int> points; class line { public: //ax+by+c=0 long long a = 0; long long b = 0; long long c = 0; static void calInteract(line l1, line l2); line(long long x1, long long y1, long long x2, long long y2); }; //關鍵函數邏輯: //使用公式代入 long long temp = a1 * b2 - a2 * b1; pair<double,double> ans; if (temp != 0) { x = (1.0 * (c2 * b1 - c1 * b2)) / (1.0 * temp); y = (1.0 * (a2 * c1 - a1 * c2)) / (1.0 * temp); ans = pair<double, double>(double(x), double(y)); points.insert(pair<pair<double, double>, int>(ans, 1)); }
最初我使用了第一種實現思路,可是發現沒有辦法很好地實現浮點數部分的去重,因此我使用了第二種實現策略,第二種實現策略的好處在於,map自身集成了去重的功能,因此能夠很好的利用這一點,達到一個簡化代碼提升效率的目的。
當測試數據爲2000條數據時,性能測試以下:
調用細節以下:
能夠看到具體調用最爲頻繁的是核心算法,計算相交直線的部分。
直線交點計算部分,爲了簡化斜率的討論,直接採用了直線方程的通常式(\(ax+by+c=0\)):
消除warning:
單元測試: