diff --git a/md/o59_may03_signal.md b/md/o59_may03_signal.md index bf8bf6c..25203c8 100644 --- a/md/o59_may03_signal.md +++ b/md/o59_may03_signal.md @@ -1,13 +1,69 @@ -ในข้อนี้เราเขียนระยะห่างระหว่าง access point $i$ และ access point $j$ ด้วย $d(i, j)$ ซึ่งเราจะนิยามให้ $d(i, j) = (x_i-x_j)^2 + (y_i-y_j)^2$ +เราจะเขียนระยะห่างกำลังสองระหว่าง access point $i$ และ access point $j$ ด้วย $d(i, j)$ ซึ่งโดยนิยาม $d(i, j) = (x_i-x_j)^2 + (y_i-y_j)^2$ -สมมติก่อนว่าเรารู้ค่า $P$ แล้ว ค่า $a[i][j]$ ซึ่งบอกว่า access point $i$ คุยกับ access point $j$ ได้ไหม ควรจะมีค่าเป็น $1$ ก็ต่อเมื่อ $d(i, j) \leq P^2$ เท่านั้น มิเช่นนั้นควรจะมีค่าเป็น $0$ +สมมติก่อนว่าเรารู้ค่า $P$ แล้ว กำหนดให้ $b[i][j]$ บอกว่า access point $i$ คุยกับ access point $j$ ได้ไหม เรารู้ว่า $b[i][j]$ ควรจะมีค่าเป็น $1$ ก็ต่อเมื่อ $d(i, j) \leq P^2$ มิเช่นนั้นควรจะมีค่าเป็น $0$ -หากเรานำค่า $a[i][j]$ **จริง**ทั้งหมดมาเรียงกันจากน้อยไปมากตามค่า $d(i, j)$ ที่เกี่ยวข้องกับมัน จะได้ลำดับใหม่คือ $S_1, S_2, S_3, ..., S_m$ ($m =$ จำนวนข้อมูล) เราจะได้ว่า จะมี index $k$ โดย $0 \leq k \leq m$ ที่ $S_i = 1$ สำหรับ $1 \leq i \leq k$ และ $S_i = 0$ สำหรับ $k< i \leq m$ กล่าวคือลำดับจะเป็นเลข $1$ ตลอดไปจนถึงจุด ๆ หนึ่ง แล้วเปลี่ยนเป็น $0$ ตลอดจนจบลำดับ (หรืออาจจะไม่มี $1$ เลยก็ได้) +หากเรานำเส้นเชื่อมทั้งหมดระหว่าง access point สองตัวใด ๆ มาเรียงกันจากน้อยไปมากตามค่า $d(i, j)$ จะได้ลำดับของเส้นเชื่อมคือ $E_1, E_2, E_3, ..., E_m$ (โดย $m = n^2$ ซึ่งคือจำนวนเส้นเชื่อม) ให้ $b[E_k]$ แทน $b[i][j]$ สำหรับ $i, j$ ที่สัมพันธ์กับเส้นเชื่อม $E_k$ เราจะทราบว่าลำดับ $b[E_1], \dots, b[E_m]$ จะเป็น $1$ ตลอดไปจนถึงจุด ๆ หนึ่ง แล้วเปลี่ยนเป็น $0$ ตลอดจนจบลำดับ (หรืออาจจะไม่มี $0$ เลยก็ได้) หรือสามารถเขียนเป็นคณิตศาสตร์ได้ว่า จะมี index $k$ ที่ทำให้ $b[E_i] = 1$ สำหรับทุก $1 \leq i \leq k$ และ $b[E_i] = 0$ สำหรับทุก $k < i \leq m$ -ดังนั้นเพื่อที่จะหาคำตอบที่ดีที่สุด เราจะสร้างลำดับ $T$ โดยวิธีคล้ายกับการสร้างลำดับ $S$ ข้างต้น แต่เราจะใช้ค่า $a[i][j]$ **ที่โจทย์ให้มา**แทน จากนั้นเราจะไล่เทียบกับ $S$ ที่เป็นไปได้ทั้งหมดโดยการเปลี่ยนค่า $k$ ไปเรื่อย ๆ จาก $k=0$ ถึง $k=m$ (ซึ่ง $k$ คือจุดสุดท้ายที่ลำดับ $S$ มีค่าเป็น $1$) แล้วในแต่ละครั้งของการไล่ เราจะคำนวณหาจำนวนสมาชิกของ $T$ ที่ไม่เหมือน $S$ คำตอบของเราจะมีค่าเท่ากับค่าที่น้อยที่สุดของจำนวนที่สมาชิกที่ต่างกันในแต่ละครั้งของการไล่ +ดังนั้นเพื่อที่จะหาคำตอบที่ดีที่สุด เราจะสร้างลำดับโดยวิธีคล้ายกับการสร้างลำดับ $b[E_i]$ ข้างต้น แต่เราจะใช้ค่า $a[i][j]$ ที่โจทย์ให้มาแทน นั่นคือจะได้ลำดับ $a[E_i]$ -แต่ข้อนี้มีข้อควรระวังคือ เราจะไม่สามารถใช้ $k$ บางค่าได้ เนื่องจากอาจจะมีกรณีที่ระยะทางมีค่าเท่ากัน ยกตัวอย่างเช่น ลำดับ $T$ ของเราอาจจะมีค่า $d(i, j)$ ที่สอดคล้องเท่ากับ $10, 25, 30, 30, 30, 45, 60$ สังเกตว่าถ้าเราให้ $k = 3$ จะได้ว่า $30 \leq P^2$ และ $30 > P^2$ ในเวลาเดียวกัน ซึ่งไม่สามารถเป็นไปได้ ดังนั้นเวลาไล่ค่า $k$ ให้เราข้าม index พวกนี้ไปเลย +จากนั้นเราจะหาว่าลำดับ $a[E_i]$ ที่เราได้มา ใกล้เคียงกับการเป็นลำดับ $b[E_i]$ มากแค่ไหน พูดอีกอย่างคือการหาว่าเราต้องสลับ $1$ กับ $0$ อย่างน้อยกี่ตัวที่จะทำให้ลำดับ $a[E_i]$ เป็นลำดับที่เริ่มจาก $1$ ตลอดไปจนถึงจุด ๆ หนึ่ง แล้วเปลี่ยนเป็น $0$ ตลอดจนจบลำดับ (หรืออาจจะไม่มี $0$ เลยก็ได้) -ในการคำนวณหาจำนวนสมาชิกที่ต่าง ให้เราเก็บจำนวนของ $0$ จนถึงตำแหน่ง $k$ เพื่อใช้ในการคำนวณคำตอบ จากนี้ เราสามารถคำนวณจำนวนของ $1$ หลังตำแหน่ง $k$ ได้ด้วย ดังนั้นเราก็จะสามารถคำนวณคำตอบในแต่ละครั้งของการเปลี่ยนค่า $k$ ได้เร็ว ๆ +เราทำได้โดยการไล่เทียบกับ $b[E_i]$ ที่เป็นไปได้ทั้งหมดโดยการเปลี่ยนค่า $k$ ไปเรื่อย ๆ จาก $k=0$ ถึง $k=m$ (ซึ่ง $k$ คือจุดสุดท้ายที่ลำดับ $b[E_i]$ มีค่าเป็น $1$ ทุกตัว) แล้วในแต่ละครั้งของการไล่ เราจะคำนวณหาจำนวนสมาชิกของ $a[E_i]$ ที่ไม่เหมือน $b[E_i]$ คำตอบของเราจะมีค่าเท่ากับค่าที่น้อยที่สุดของจำนวนที่สมาชิกที่ต่างกันในแต่ละครั้งของการไล่ -time complexity ของวิธีนี้จะเท่ากับ $\mathcal{O}(n^2 \log n)$ จากการ sort ลำดับ $T$ ซึ่งมีความยาวเท่ากับ $m = n^2$ +แต่ข้อนี้มีข้อควรระวังคือ เราจะไม่สามารถใช้ $k$ บางค่าได้ เนื่องจากอาจจะมีกรณีที่ระยะทางมีค่าเท่ากัน ยกตัวอย่างเช่น ลำดับของเราอาจจะมีค่า $d(i, j)$ ที่สอดคล้องเท่ากับ $10, 25, 30, 30, 30, 45, 60$ สังเกตว่าถ้าเราให้ $k = 3$ จะได้ว่า $30 \leq P^2$ และ $30 > P^2$ ในเวลาเดียวกัน ซึ่งไม่สามารถเป็นไปได้ ดังนั้นเวลาไล่ค่า $k$ ให้เราข้าม index พวกนี้ไปเลย + +ในการคำนวณหาจำนวนสมาชิกที่ต่าง ให้เราเก็บจำนวนของ $1$ จนถึงตำแหน่ง $k$ เพื่อใช้ในการคำนวณคำตอบ เราสามารถคำนวณจำนวนของ $0$ หลังตำแหน่ง $k$ ได้ด้วย ดังนั้นเราก็จะสามารถคำนวณคำตอบในแต่ละครั้งของการเปลี่ยนค่า $k$ ได้เร็ว ๆ การเปรียบเทียบนี้ควรทำได้ใน $\mathcal{O}(n^2)$ + +time complexity ของวิธีนี้จะเท่ากับ $\mathcal{O}(n^2 \log n)$ จากการ sort ลำดับซึ่งมีความยาวเท่ากับ $m = n^2$ + +```cpp +#include +using namespace std; +#define x first +#define y second + +pair p[200]; + +struct Edge { + int i, j, d, a; + bool operator < (const Edge & o) const { + return d < o.d; + } +}; + +vector v; +vector qs; + +int main(){ + ios_base::sync_with_stdio(false); cin.tie(NULL); + int n; cin >> n; + + for (int i = 1; i <= n; i++) cin >> p[i].x >> p[i].y; + + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + int report; cin >> report; + int dis = (p[i].x-p[j].x)*(p[i].x-p[j].x) + + (p[i].y-p[j].y)*(p[i].y-p[j].y); + v.push_back({i, j, dis, report}); + } + } + + sort(v.begin(), v.end()); + int n2 = v.size(); + qs.resize(n2); + + qs[0] = v[0].a; + for (int i = 1; i < n2; i ++) qs[i] = qs[i-1] + v[i].a; + + int mn = 1e9; + for (int i = 0; i < n2; i ++) { + if (v[i].d == v[i+1].d) continue; + int error = (i+1 - qs[i]) + (qs[n2-1] - qs[i]); + mn = min(mn, error); + } + cout << mn; + + return 0; +} +```