ZOJ 3041 City Selection(二维比较,排序分析)

ZOJ 3041 City Selection(二维比较,排序分析)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3041

题意:

       现在有m个工厂和n个打算建城市的地点(给出所有点的x和y坐标,且(0,0)位于2维坐标轴的中心),如果有一个工厂在一个打算建城市地点的左上角(就算在边界也算),那么该地点就不能建城市(因为会被污染).现在要你输出所有可以建城市的点坐标.

分析:

        如果有工厂 x 坐标 <= 城市 x 坐标且工厂 y 坐标 >= 城市 y 坐标,那么该城市点不可行.(其实就是看该城市点的左上角是否有一个工厂点)


        问题1:如果我们想知道点i(xi,yi)是否可建城市,我们需要怎么做?

        只要看二维坐标轴上,在点 i 的左边是否有一个工厂点的 y 坐标 >= yi 即可。


        问题2:如何快速的确定所有的城市点是否可行?

        我们通过将所有工厂和城市点按x从小到大,(如果x相等,y从大到小,如果xy都相等,就把工厂排在城市前面)的顺序排序. 

        现在我们确定了x坐标一定是从小到大排序的,所以如果我们当前考虑第i个点(该点是城市)是否可行时?我们只要从0到i-1这些点中找出是否有一个工厂的y坐标大于等于它的y坐标就行(因为这前面任意工厂的x坐标肯定<=该地点的x坐标).

        所以程序中我们用y来记录我们当前所遇到过的所有工厂中y坐标的最大值.如果这个最大值依然小于当前城市点的y坐标,那么就不可能有妨碍该城市的工厂存在了.(因为只有城市点左边的工厂才可能妨碍该点建立城市,自己想想是不是)

AC代码(新):

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;

struct Node
{
    int x;
    int y;
    bool f;//ture时表示工厂factory

    Node(int x,int y,bool f):x(x),y(y),f(f){}

    bool operator<(const Node &rhs)const
    {
        return x<rhs.x || (x==rhs.x && y<rhs.y);
    }
};

bool cmp(const Node &lhs,const Node &rhs)
{
    return lhs.x<rhs.x || (lhs.x==rhs.x && lhs.y>rhs.y)
        || (lhs.x==rhs.x && lhs.y==rhs.y && lhs.f);
}

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)==2)
    {
        //所有点都保存在vc1中
        vector<Node> vc1;
        for(int i=1;i<=n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            vc1.push_back(Node(x,y,false));
        }
        for(int i=1;i<=m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            vc1.push_back(Node(x,y,true));
        }
        sort(vc1.begin(),vc1.end(),cmp);

        //vc2中只保存可建城市的点
        vector<Node> vc2;
        int max_y=-1e9-1;//当前最大的y坐标
        for(int i=0;i<vc1.size();i++)
        {
            if(vc1[i].f==true)//工厂点
            {
                max_y=max(max_y, vc1[i].y);
            }
            else//城市点
            {
                if(vc1[i].y > max_y) vc2.push_back(vc1[i]);
            }
        }

        sort(vc2.begin(),vc2.end());

        printf("%d\n",vc2.size());
        for(int i=0;i<vc2.size();i++)
            printf("%d %d\n", vc2[i].x, vc2[i].y);
    }
}

AC代码:

虽然本代码能AC,但是是错的。对于下列数据:

3 3
0 1
-2 1
1 3
-2 2
2 0
4 4
会得到错误的输出:

2

-2 1

1 3

正确的输出应该是:

1

1 3

原因在于代码中按x从小到大,y从小到大,工厂优先排序的。应该按x从小到大,y从大到小,工厂优先排序。因为当两个点x坐标相同时,我们应该优先考虑y坐标大的点更新当前工厂最大y值。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define INF 2e10
const int maxn=200000*2+10;

struct Node
{
    int x,y;
    bool f;//true时表工厂
    bool operator<(const Node& rhs)const
    {
        return x<rhs.x ||(x==rhs.x && y<rhs.y)||(x==rhs.x && y==rhs.y && f);
    }
}nodes[maxn];

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)==2)
    {
        for(int i=0;i<n;++i)
        {
            scanf("%d%d",&nodes[i].x,&nodes[i].y);
            nodes[i].f=false;
        }
        for(int i=n;i<n+m;++i)
        {
            scanf("%d%d",&nodes[i].x,&nodes[i].y);
            nodes[i].f=true;
        }
        sort(nodes,nodes+n+m);

        int ans=0;//最终能建city的地方数目
        int num[maxn];
        int y=-INF;//之前所有工厂中,y的最大值
        for(int i=0;i<n+m;++i)
        {
            if(nodes[i].f==true)//工厂
                y=max(y,nodes[i].y);
            else                //城市
            {
                if(y<nodes[i].y)//可建城市
                    num[ans++]=i;
            }
        }
        printf("%d\n",ans);
        for(int i=0;i<ans;++i)
            printf("%d %d\n",nodes[num[i]].x,nodes[num[i]].y);
    }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值