One-Dimensional Battle Ships題解
題目翻譯
\(Alice\) 和 \(Bob\) 喜歡在 \(1×n\) 的表格中玩戰艦遊戲。遊戲開始時,\(Alice\) 有 \(k\) 艘戰艦,每艘戰艦長度為 \(a\) ,她需要把這些戰艦不重疊且不相鄰地放在格子中(不允許有兩艘戰艦的格子存在公共邊)。但她並不會告訴 \(Bob\) 她放的位置。
接下來,\(Bob\) 會用 \(m\) 顆炮彈嘗試打中 \(Alice\) 的戰艦,每顆炮彈會選擇一個格子打擊。但由於 \(Alice\) 喜歡作弊,所以她不會告訴 \(Bob\) 什麼時候擊中了戰艦。請你幫助 \(Bob\) 判斷,在第幾次發射炮彈後,\(Alice\) 一定會有一艘戰艦被擊中。
思路詳解
這道題其實普遍的方法就兩種, 因為 STRADUST 大佬寫了二分做法, 所以我就來寫一下 STL 做法。(主要原因還是現在在學 STL , 畢竟學了什麼就要用什麼)(如想檢視二分做法, 點這裡)
迴歸正題, 上文已經說了我們要用 STL 來解決這道題, 那麼, 怎麼解決呢?
首先, 我們考慮一個區間 \([l, r]\) 。如果我們想在這個區間裡面放戰艦, 那麼就根據排列組合, 既然兩艘艦艇不能挨在一起, 那麼就考慮往每艘艦艇的左邊都多佔一個, 這樣就可以兩條戰艦挨在一起了。 但這樣就會出現最左邊的戰艦貼著左邊, 所以我們需要在區間 \([l, r]\) 的左邊再加一格, 來保證貼左的問題。 所以, 這個區間的最終的 \(MAX\{可放置艦艇數量\} = (r - l + 1 + 1) / a (a 如題目所示)\)
我們記錄一下整個的最大可放置艦艇數為 \(smax\) 。對於每次對於一個獨立區間 \([l, r]\) 的轟炸, 假設轟炸位置為 \(mid\) , 因為 \(mid\) 處不能有戰艦了, 所以原來的區間 \([l, r]\) 也就變成了兩個單獨的能放置戰艦的區間 \([l, mid - 1]\) 和 \([mid + 1, r]\) 。那麼, 這次操作對 \(smax\) 的改動為 \(smax - (r - l + 1 + 1) / a + (mid - 1 - l + 1 + 1) / a + (r - mid - 1 + 1 + 1) / a\) 。這樣做似乎有點難用 STL , 那我們再將剛才涉及的那三個區間拿出來變個形: \((l - 1, r + 1), (l - 1, mid), (mid, r + 1)\)
程式碼:
#include <cstdio>
#include <algorithm>
#include <set>
using namespace std;
set <int> s1;
void read (int &a) {
a = 0;
char c = getchar ();
bool bl = 0;
while (c < '0' || c > '9') {
if (c == '-') {
bl = 1;
}
c = getchar ();
}
while (c >= '0' && c <= '9') {
a = (a << 1) + (a << 3) + (c ^ 48);
c = getchar ();
}
a = bl ? -a : a;
}
void read (long long &a) {
a = 0;
char c = getchar ();
bool bl = 0;
while (c < '0' || c > '9') {
if (c == '-') {
bl = 1;
}
c = getchar ();
}
while (c >= '0' && c <= '9') {
a = (a << 1) + (a << 3) + (c ^ 48);
c = getchar ();
}
a = bl ? -a : a;
}
int main () {
int n, k, a;
int m;
int sum = 0;
read (n), read (k), read (a);
//初始區間
s1.insert(n + 1);
s1.insert(0);
sum = n / a;
read (m);
for (int l = 1; l <= m; l ++) {
int x;
read (x);
s1.insert(x);
//找到所在區間
set <int> :: iterator i = s1.lower_bound(x), j = s1.upper_bound(x);
i --;
sum -= (*j - *i - 1) / a;
sum += (x - *i - 1) / a;
sum += (*j - x - 1) / a;
if (sum < k) {//判斷是否撒謊
printf ("%d", l);
return 0;
}
}
printf ("-1");
}