分類:math
probability
[計蒜客 商湯科技的行人檢測(困難)]
在這道題中,我們將行人的移動過程抽象為 旋轉、伸縮、平移,有 4 個 移動引數:θ,
scal
e,dx
,dy
。每次行人的移動過程會將行人對應的 nn 個點全部依次應用旋轉、伸縮、平移,對於平移前的點 (x, y)(x,y),進行每種操作後的座標如下:
旋轉後的座標為:(x
cosθ−y
sinθ,x
sinθ+y
cosθ
) ;
伸縮後的座標為:(x
×sca
le,y
×sca
le) ;
平移後的座標為:(x
+dx,
y+dy
) 。
由於行人移動的特殊性,我們可以確保
0ale≤
10 。和簡單版本不同的是,這道題處理的座標為浮點數而非整數。
很顯然,通過變換前後的正確座標,很容易算出行人的移動引數,但問題沒有這麼簡單。由於行人實際的移動並不會完全按照我們預想的方式進行,因此,會有一部分變換後的座標結果不正確,但可以確保 結果不正確的座標數量嚴格不超過一半。
你現在作為商湯科技的實習生,接手了這個有趣的挑戰:算出行人的移動引數。如果不存在一組合法的移動引數,則隨意輸出一組引數;如果有多種合法的移動引數,輸出其中任意一組合法的即可。
輸入格式
第一行輸入乙個整數
n ,表示行人抽象出的點數。
接下來
n行,每行
4 個 浮點數。前兩個數表示平移前的座標,後兩個數表示平移後的座標。
座標範圍在 −10
9 到 109
之間,輸入的座標都保留到
6 位小數。
對於中等版本,1≤
n≤500 ;
對於困難版本,1≤
n≤105
。輸出格式
第一行輸出乙個浮點數
θ ,第二行輸出乙個浮點數 sc
ale ,第三行輸出兩個浮點數 dx
,dy 。
建議輸出保留到
10 位小數或以上。我們會按照 10−
3 的精度判斷是否有超過一半的點變換後的座標重合。
中等版本
在中等版本中,除了平移之外,還加入了旋轉和拉伸。可以發現只需要列舉哪兩對點是正確變換的,就可以計算出對應的拉伸、旋轉、平移的量,從而驗證是否有嚴格超過一半的點對滿足這組變換。時間複雜度o(
n3) 。注意特判只有乙個點對的情況。
困難版本
在困難版本中,點對數
n 從
100公升級到了
100000
。其演算法本質並沒有發生改變,依然是列舉兩對點,然後驗證。但是其列舉順序,必須從按順序列舉,改為隨機列舉,以避免最壞複雜度。注意到錯誤的點對數嚴格不超過一半,因此我們有超過 1/
4 的概率,列舉到的兩對點就是正確的。對應的,列舉一次失敗的概率就不足 3/
4 。這意味著:隨機列舉
10 次,失敗的概率不足
5.6%
;隨機列舉
20 次,失敗的概率不足
0.3%
;隨機列舉
50 次,失敗的概率不足
0.00005
% 。所以,只需要常數次列舉,基本可以保證找到答案。時間複雜度o(
n)。注意:
這題精度問題比較嚴重,盡量不要用at
an來求
θ ,精度誤差會比較大。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
typedef
long
long ll;
typedef
long
double lb;
typedef
unsigned
long
long ull;
typedef pair pii;
typedef pairpll;
typedef pairplb;
typedef
vector
vi;
const
int inf = 0x3f3f3f3f;
const ll infl = 0x3f3f3f3f3f3f3f3fll;
const
long
double pi = acos(-1.0);
const
long
double eps = 1e-4;
void debug()
template
void debug (t f, r ...r)
template
inline
void umax(t &a, t b)
template
inline
void umin(t &a, t b)
template
inline
bool scan_d (t &ret)
template
void print(t x)
template
void println(t x)
const
int maxn = 1e5 + 5;
int n;
struct qnode
} cmd[maxn];
int sgn(const lb& a, const lb& b)
plb f(qnode qd, lb sita, lb scale, lb dx, lb dy)
int calc(lb sita, lb scale, lb dx, lb dy)
return cnt;
}inline lb dis(lb ax, lb ay, lb bx = 0.0, lb by = 0.0)
int main()
lb sita, scale, dx, dy, delta_x[2], delta_y[2], up, dw;
lb ans[4];
if(n == 1)
int cnt = 0;
for(int _ = 100; _--; )
cout
<< fixed << setprecision(11) << ans[0] << endl;
cout
<< fixed << setprecision(11) << ans[1] << endl;
cout
<< fixed << setprecision(11) << ans[2] << " "
<< ans[3] << endl;
}#ifdef ___local_wonzy___
cout
<< "time elapsed: "
<< 1.0 * clock() / clocks_per_sec * 1000
<< " ms."
<< endl;
#endif // ___local_wonzy___
return
0;}
計蒜客 商湯科技的行人檢測(隨機化 計算幾何)
題目鏈結 簡單中等 困難簡單版本 直接統計答案,數目到達一半即可。include using namespace std define rep i,a,b for int i a i b i define dec i,a,b for int i a i b i int n int a,b,c,d p...
計蒜客 商業資訊共享
有 n個公司,從每個公司都能單向地向另外乙個公司分享最新商業資訊,因為他們之間有著某種合作,你需要解決兩個問題 現在有乙個最新的商業資訊,至少需要告訴多少個公司,使得所有的公司最終都能得到該資訊。在原有基礎上,至少需要再讓多少對公司建立這種合作,使任意乙個公司獲得某個最新商業資訊後,經過若干次分享,...
2017計蒜之道初賽第四場 商湯科技的安全令牌
商湯科技致力於引領人工智慧核心 深度學習 技術突破,構建人工智慧 大資料分析行業解決方案。作為一家人工智慧公司,用機器自動地解決各類實際問題自然不在話下。近日,商湯科技推出了一套安全令牌,令牌如下圖所示 安全令牌上的小孔有 nn 行 mm 列,不過有些行和有些列已經用導線整體焊接了,共有 kk 根導...