2020算法设计竞赛 I、匹配星星

链接:https://ac.nowcoder.com/acm/contest/3005/I
来源:牛客网

天上有n颗星星,每颗星星有二维坐标(xi,yi)(x_i, y_i)(xi,yi),还有一个属性值ziz_izi,若两颗星星A, B满足xA<xBx_A < x_BxA<xByA<yBy_A < y_ByA<yBzA<zBz_A < z_BzA<zB,则这两颗星星可以配成一对,每颗星星最多只能在一对之中,求最多能配成多少对星星。

思路:贪心思想;

我们先按x从小到大排序,如果x相等,就按y从大到小;

然后接下来遍历数组;

遇到z值为0的就放进容器;遇到1的就去寻找容器中小于此数的y值且在容器中y最大的那个数进行匹配;然后将这个数删除

不断重复这个过程即可

证明:作者:nocriz
链接:https://ac.nowcoder.com/discuss/365889
来源:牛客网

假设最优方案中排序后Z=1Z = 1Z=1的第 1 个没有按贪心策略匹配的点 iii ,在设 iii 在Z=0Z = 0Z=0中它能匹配的 yyy 最大的点为 jjj,如果 jjj 被点 kkk 匹配了,有两种情况:

    • 原先 iii 没有和任何匹配,则直接去掉 kkk 的匹配,将 iii 和 jjj 匹配。
    • 原先 iii 和 mmm 匹配,则将 kkk 改成和 mmm 匹配,将 iii 和 jjj 匹配,由于Yj>YmY_j>Y_mYj>Ym, 这样的匹配一定是成立的。并且修改后的匹配数不会变少,因此按照该贪心策略可以得到最优解。
  •  1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn=3e5+10;
     5 struct node{
     6     int a,b,c;
     7 }p[maxn];
     8 int n;
     9 bool cmp(node x,node y)
    10 {
    11     if(x.a==y.a) return x.b>y.b;
    12     else return x.a<y.a;
    13 }
    14 int main()
    15 {
    16     cin>>n;
    17     for( int i=0;i<n;i++ ) cin>>p[i].a>>p[i].b>>p[i].c;
    18     sort(p,p+n,cmp);
    19     multiset<int> pool;
    20     int ans=0;
    21     for( int i=0;i<n;i++ ){
    22         if( p[i].c ){
    23             multiset<int>::iterator it;
    24             it=pool.lower_bound( p[i].b );
    25             if( it!=pool.begin() ){
    26                 --it;
    27                 pool.erase(it);
    28                 ans++;
    29             }
    30         }
    31         else pool.insert( p[i].b );
    32     }
    33     cout<<ans<<endl;
    34     return 0;
    35 }

猜你喜欢

转载自www.cnblogs.com/pangbi/p/12298316.html