1. 程式人生 > >洛谷 P1158 導彈攔截(不是那個DP) 解題報告

洛谷 P1158 導彈攔截(不是那個DP) 解題報告

HR turn ons strong 自信心 貪心 做了 結果 輸入格式

P1158 導彈攔截

題目描述

經過1111年的韜光養晦,某國研發出了一種新的導彈攔截系統,凡是與它的距離不超過其工作半徑的導彈都能夠被它成功攔截。當工作半徑為0時,則能夠攔截與它位置恰好相同的導彈。但該導彈攔截系統也存在這樣的缺陷:每套系統每天只能設定一次工作半徑。而當天的使用代價,就是所有系統工作半徑的平方和。

某天,雷達捕捉到敵國的導彈來襲。由於該系統尚處於試驗階段,所以只有兩套系統投入工作。如果現在的要求是攔截所有的導彈,請計算這一天的最小使用代價。

輸入輸出格式

輸入格式:

第一行包含 4 4 個整數\(x_1,y_1,x_2,y_2\) ,每兩個整數之間用一個空格隔開,表示這兩套導彈攔截系統的坐標分別為\((x_1, y_1)\)

\((x_2, y_2)\)。 第二行包含1個整數\(N\),表示有 \(N\)顆導彈。接下來\(N\)行,每行兩個整數\(x,y\),中間用 一個空格隔開,表示一顆導彈的坐標\((x, y)\)。不同導彈的坐標可能相同。

輸出格式:

一個整數,即當天的最小使用代價。

【數據範圍】

對於 10% 的數據, \(N=1\)

對於 20% 的數據, \(1≤N≤2\)

對於 40% 的數據, \(1≤N≤100\)

對於 70% 的數據, \(1≤ N≤1000\)

對於 100% 的數據,\(1 ≤ N ≤ 100000\),且所有坐標分量的絕對值都不超過1000。


事實證明,並不是多做了幾個省選模板的數據結構就可以讓我變得強一些。這個題我想+A大概花了有一個小時左右。雖說可以說是第一次看見這樣類似的題,但想這麽長時間還是挺打擊自信心的。

首先可能因為今晚做的一道貪心題,我先入為主胡亂打了一波貪心,還沒交就被我hack掉了,但我想看看能騙多少分,還是交了上去,恩40海星了。

以為是貪心不完善,結果想了好久沒辦法。。

輾轉畫圖中,我發現可以先處理一個點對所有的點的距離,然後枚舉這些距離並算出另一個點要開的大小。首先排序保證單調,然後預處理另一個點。

我覺得可以理解為,通過排序使一個維度單調,然後暴力枚舉令一個維度更新答案。


code:

#include <cstdio>
#include <algorithm>
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
const int N=100010;
const int inf=0x3f3f3f3f;
int x1,x2,y1,y2,mi1,mi2,mx[N];
struct node
{
    int d1,d2;
    friend bool operator <(node n1,node n2)
    {
        return n1.d1<n2.d1;
    }
}d[N];
int get(int xk,int yk,int xl,int yl)
{
    return (xk-xl)*(xk-xl)+(yk-yl)*(yk-yl);
}
int main()
{
    scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    int x,y,n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&x,&y);
        d[i].d1=get(x1,y1,x,y);
        d[i].d2=get(x2,y2,x,y);
    }
    std::sort(d+1,d+1+n);
    for(int i=n;i>=0;i--)
        mx[i]=max(mx[i+1],d[i].d2);
    int ans=inf;
    for(int i=0;i<=n;i++)
        ans=min(ans,mx[i+1]+d[i].d1);
    printf("%d\n",ans);
    return 0;
}

2018.6.15

洛谷 P1158 導彈攔截(不是那個DP) 解題報告