24h購物| | PChome| 登入
2013-10-02 08:35:01| 人氣3,302| 回應0 | 上一篇 | 下一篇

[UVA][二分貪婪] 12255 - Underwater Snipers

推薦 0 收藏 0 轉貼0 訂閱站台

King Motashota is in a war against the mighty Bachchaloks. He has formed a well-trained army of snipers, and planning to use them as much as possible. In one of the missions, he has S snipers. They will be dispatched to get rid of the soldiers guarding the bank of the river 'Nodi'.

 

From satellite images, Motashota has located positions of all enemy soldiers. Now, the plan is, snipers will take their positions. They are excellent swimmers, so, you can assume that they won't get caught, while taking position. Upon order from Motashota, they will start shooting enemy soldiers. A sniper can shoot a soldier, if euclidean distance between the soldier and sniper is no more than D. After the snipers get rid of all the soldiers, they can proceed with the operation. So, it is important for them to position the snipers in such a way that, all soldiers are within the range of at least one sniper.

 

In addition, when snipers start shooting, the guards will be alert, and thus, snipers can't change their position, they can only continue shooting from their position.

 

The river bank is defined by the horizontal line y = k. All points (x,y) where y>k is in the enemy territory, and if y<k, then it's on the water. You will be given location of N soldiers, strictly in the enemy territory, you have to place S soldiers in the water, so that, they can kill all soldiers. For security reasons, the snipers should be as far from the bank as possible. For any sniper in position (xi,yi), the distance from the bank is |yi-k|. If, for all snipers, the minimum of them is M=min{|yi-k|}, you have to maximize M.

 

Both the soldiers and snipers are really superstitious. They will stay only in integer coordinates.

 

Input

First line contains an integer T(1≤T≤100), the number of test cases.

 

This is followed by T test cases. Each test case starts with four integers, k(-108≤k≤108),  N(1≤N≤10000), S(1≤S≤10000) and D(1≤D≤109), the position of the bank, number of guards and number of snipers, and the range of the snipers.

 

This is followed by N lines, each containing a pair of integers (xi, yi) the position of ith guard (-108 xi ≤ 108, k < yi ≤ 108).

 

There is a blank line before each test case.

 

Output

For each test case, output the case number followed by an integer, M, which is defined in the statement. If the snipers can’t kill all guards, output: “IMPOSSIBLE”.

 

 

Sample Input                               Output for Sample Input

2

 

0 3 2 4

1 1

3 2

9 1

 

0 3 1 4

1 1

3 2

9 1

Case 1: 2

Case 2: IMPOSSIBLE

 


Problemsetter: Manzurur Rahman Khan, Special Thanks: Jane Alam Jan, D. Kisman

題目描述:

在 2D 座標上,y = k畫分兩個區塊,一面是陸地,另一面是水。

要派出 S 位狙擊手在水中,將陸上的士兵殲滅。

而每個狙擊手的射程固定,要最大化最小狙擊手離岸邊的距離,以減少士兵警戒心。

題目解法:

二分這個最小的離岸邊距離,對於每組二分,進行貪婪檢查。

將士兵座標按照 x 座標由小到大排序,優先派出狙擊手盡可能地在極限範圍射到。

每次考慮一位最左邊的士兵在新的狙擊手範圍內,並且消除其他在這名狙擊手範圍內的士兵。

題目要求每個人的座標都要是整數!

#include <stdio.h>
#include <vector>
#include <math.h>
#include <algorithm>
using namespace std;
#define LL long long
struct Pt {
    LL x, y;
    bool operator<(const Pt &a) const {
        if(x != a.x)    return x < a.x;
        return y > a.y;
    }
};
Pt p[10000];
LL K, D;
int N, S;
int check(int M) {
    int i = 0, used = 0;
    Pt sniper;
    sniper.y = K-M;
    do {
        LL a, b;
        b = p[i].y - (K-M);
        if(b > D)    return 0;
        a = (LL)sqrt(D*D-b*b);
        sniper.x = a+p[i].x, sniper.y = K-M;
        i++, used++;
        while(i < N) {
            if((sniper.x-p[i].x)*(sniper.x-p[i].x)+(sniper.y-p[i].y)*(sniper.y-p[i].y) > D*D)
                break;
            i++;
        }
    } while(i < N && used <= S);
    return used <= S && i == N;
}
int main() {
    int testcase, cases = 0;
    int i, j, k;
    scanf("%d", &testcase);
    while(testcase--) {
        scanf("%lld %d %d %lld", &K, &N, &S, &D);
        for(i = 0; i < N; i++)
            scanf("%lld %lld", &p[i].x, &p[i].y);
        sort(p, p+N);
        LL l = 0, r = D, mid;
        LL ret;
        printf("Case %d: ", ++cases);
        if(check(0) == 0) {
            puts("IMPOSSIBLE");
            continue;
        }
        while(l <= r) {
            mid = (l+r)/2;
            if(check(mid))
                l = mid+1, ret = mid;
            else
                r = mid-1;
        }
        printf("%lld\n", ret);
    }
    return 0;
}

台長: Morris
人氣(3,302) | 回應(0)| 推薦 (0)| 收藏 (0)| 轉寄
全站分類: 教育學習(進修、留學、學術研究、教育概況) | 個人分類: UVA |
此分類下一篇:[UVA][TSP] 10937 - Blackbeard the Pirate
此分類上一篇:[UVA][二分maxflow] 10983 - Buy one, get the rest free

是 (若未登入"個人新聞台帳號"則看不到回覆唷!)
* 請輸入識別碼:
請輸入圖片中算式的結果(可能為0) 
(有*為必填)
TOP
詳全文