POJ3069 -- Saruman's Army
阿新 • • 發佈:2020-08-02
題意:
直線上有N個點。 點i的位置是Xi。從這N個點中選擇若干個,給它們加上標記。 對每一個點,其距離為R以內的區域裡必須有帶有標記的點(自己本身帶有標記的點, 可以認為與其距離為 0 的地方有一個帶有標記的點)。 在滿足這個條件的情況下, 希望能為儘可能少的點新增標記。 請問至少要有多少點被加上標記?
Ps:多組輸入,直到N / R = -1時候結束
輸入
0 3
10 20 20
10 7
70 30 1 7 15 20 50
-1 -1
輸出
2
4
解析:區間型別的貪心題。開始將最左邊的點設為未被覆蓋的點bg,向右尋找至第一個小於或等於bg + R的點,此時可以將該點標記為p,接著p其實也覆蓋了p + R,那找到第一個大於p + R的點作為下一個最左邊未被覆蓋的點,依次下去。下面大概草草的畫了一個圖作為理解。
AC程式碼:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; typedef long long LL; const int num = 1005; int r, n, p, res; int a[num]; int main() { ios::sync_with_stdio(false); while(cin >> r >> n && (r != -1 || n != -1)) { memset(a, 0, sizeof(a)); res = 0, p = 0; for(int i = 1; i <= n; i++) cin >> a[i]; sort(a + 1, a + n + 1); int i = 1; //此時運動到第i個點 while(i <= n) { int bg = a[i]; //表示當前未覆蓋的最左邊位置 for(int j = i + 1; ; j++) //找到bg最右邊且小於r的點進行標記 { if(a[j] - bg > r) { p = a[j-1]; //將標記點記錄 i = j; //更新當前位置 res++; //標記點數量增加 break; } } for(int j = i; ; j++) //標記點還能覆蓋其右邊小於r的位置 { if(a[j] - p > r) //當該點大於r時, 重新作為當前未覆蓋的最左邊位置 { i = j; //更新當前位置 break; } } } cout << res << endl; } return 0; }