CF 556D Case of Fugitive 根據島嶼選擇橋(貪心)

http://codeforces.com/contest/556/problem/D


題意:給你n個島嶼 m個橋,島嶼在一條線上

            給島嶼的左座標與又座標(L,R).從左到右按順序給每個島的L,R

           再給你每個橋的長度,每個橋只能用一次

           讓你用橋把島嶼連接起來,能連則輸出yes,並且輸出每兩個島嶼之間的橋的編號

            連接的要求是,每個橋要能連接兩個相鄰島嶼,又不能越出兩個島嶼的最大距離,即x>=L[i+1]-R[i]   &&  x<=R[i+1]-L[i]     

思路:貪心,存下兩兩相鄰島嶼之間的最大距離max,最小距離min,進行排序,先是max從小到大,max相同則min從小到大

           在所有的橋裏面找,先滿足最小max的對應的min,如果找不到或者找到的橋比max打,則肯定不行,否則一直往後找


#include<set>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iostream>
#define S second
#define F first
using namespace std;
const int MAX = 200005;
typedef long long LL;
LL xx;
set< pair<LL,int> >bridge; //橋的集合
pair< pair<LL,LL>,int >island[MAX]; //先表示島嶼,以後會表示相鄰島嶼之間的屬性
int ans[MAX];
int main()
{
    int n,m,i;
    scanf("%d%d",&n,&m);
    for(i=0;i<n;i++)
        scanf("%I64d%I64d",&island[i].F.F,&island[i].F.S); //對於島嶼目前只需要 L R 的屬性
    for(i=1;i<=m;i++){
        scanf("%I64d",&xx);
        bridge.insert(make_pair(xx,i));
    }
    for(i=0;i<n-1;i++){ //“兩兩相鄰”只有n-1個
        LL i_min=island[i+1].F.F-island[i].F.S;  
        LL i_max=island[i+1].F.S-island[i].F.F;
        island[i].S=i; 
        island[i].F.F=i_max;island[i].F.S=i_min; //“兩兩相鄰”的屬性,max,min,編號i
    }
    sort(island,island+n-1);
    for(i=0;i<n-1;i++){
        set<pair<LL,int> >::iterator it;
        it=bridge.lower_bound(make_pair(island[i].F.S,0)); //找橋
        if( it==bridge.end() || (it->F)>island[i].F.F ) break;//橋沒找到 或者 橋比最大值大,則不合格
        ans[island[i].S]=it->S; //存下橋的編號
        bridge.erase(it);//刪除此橋
    }
    if(i==n-1){
        puts("Yes");
        for(i=0;i<n-2;i++) printf("%d ",ans[i]);
        printf("%d\n",ans[i]);
    }
    else puts("No");
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章