CF28A - Bender Problem(模擬 + *1600)
阿新 • • 發佈:2022-03-26
CF28A - Bender Problem(源地址自⇔CF28A)
目錄tag
⇔模擬、⇔*1600
題意
按順序給出 \(N\) 個釘子(保證相鄰兩個釘子之間的連線平行於座標軸,且沒有三個釘子位於同一直線上),現在給出 \(M\) 根金屬棒,你需要使用金屬棒將這些釘子依次圍起來,使得圍成的圖形封閉。規定如下:
- 每根金屬棒必須 \(90°\) 彎折一次(在任意整數位置);
- 允許金屬棒重疊;
- 彎折位置和兩端都需要固定到釘子上,彎折位置所固定的釘子上不能固定另外的金屬棒。
不需要使用全部的金屬棒,你需要輸出一種可能的圍繞方式,格式為: \(N\) 個數字,代表 \(N\) 個釘子每個釘子上放置的金屬棒編號,若某個釘子上放置的為兩根金屬棒的兩端,則輸出 \(-1\) 。
一組樣例,滿足 \(4 \le N \le 500\) 且為偶數,金屬棒的數量 \(2 \le M \le 500\) 且長度 \(1 \le len_M \le 2*10^5\) ,釘子的座標 \(-10^4 \le x,y \le 10^4\) 。
思路
賽時思路
這道題最主要的難點在於理解明白題目意思,之後的實現並無難度,故略。
AC程式碼
點選檢視程式碼
const int N = 2e5 + 7; int x[N], y[N], mp[N]; int v[N], ans[N], flag; int clac(int i, int j) { return abs(x[i] - x[j]) + abs(y[i] - y[j]); } int main() { int n, m; cin >> n >> m; for (int i = 1; i <= n; ++ i) cin >> x[i] >> y[i]; for (int i = 1; i <= m; ++ i) cin >> mp[i]; x[n + 1] = x[1], y[n + 1] = y[1]; x[0] = x[n], y[0] = y[n]; //這裡寫成 x 了,卡了好幾個小時... for (int t = 1; t <= 2; ++ t) { flag = 0; memset(v, 0, sizeof v); memset(ans, -1, sizeof ans); for (int i = t; i <= n; i += 2) { int len = clac(i, i - 1) + clac(i, i + 1); for (int j = 1; j <= m; ++ j) { //由於資料量較小,此處我們選擇遍歷所有金屬棒 if (v[j] == 0 && mp[j] == len) { v[j] = 1; ans[i] = j; break; } } if (ans[i] == -1) flag = 1; } if (flag == 0) { cout << "YES" << endl; for (int i = 1; i <= n; ++ i) cout << ans[i] << " "; return 0; } } cout << "NO\n"; }
錯誤次數
(補題 1 次)未考慮釘子座標為負數的情況,直接作為下標儲存(以為相鄰釘子是需要自己找的,所以使用了陣列儲存、尋找),導致 RE 。
(補題 4 次)在初始處理時寫錯陣列。
文 / WIDA
2022.03.26 成文
首發於WIDA個人部落格,僅供學習討論