洛谷 P1158 導彈攔截(不是那個DP) 解題報告
P1158 導彈攔截
題目描述
經過1111年的韜光養晦,某國研發出了一種新的導彈攔截系統,凡是與它的距離不超過其工作半徑的導彈都能夠被它成功攔截。當工作半徑為0時,則能夠攔截與它位置恰好相同的導彈。但該導彈攔截系統也存在這樣的缺陷:每套系統每天只能設定一次工作半徑。而當天的使用代價,就是所有系統工作半徑的平方和。
某天,雷達捕捉到敵國的導彈來襲。由於該系統尚處於試驗階段,所以只有兩套系統投入工作。如果現在的要求是攔截所有的導彈,請計算這一天的最小使用代價。
輸入輸出格式
輸入格式:
第一行包含 4 4 個整數\(x_1,y_1,x_2,y_2\) ,每兩個整數之間用一個空格隔開,表示這兩套導彈攔截系統的坐標分別為\((x_1, y_1)\)
輸出格式:
一個整數,即當天的最小使用代價。
【數據範圍】
對於 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) 解題報告