hdu

Walk in the Park

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 145    Accepted Submission(s): 47


Problem Description
You are responsible for inspecting the trees located in a park, to make sure they remain healthy. The location of each tree is given to you as a point in the twodimensional plane, distinct from that of every other tree. Due to recentlyreplanted grass, you are only allowed to walk through the park along a collection of paths. Each path is described by an infinite-length horizontal or vertical line in the two-dimensional plane. No tree lies on any path.

You are concerned that it may not be possible to view all the trees in the park from the paths. In particular, a tree is visible only if you can view it by standing on some path while facing in a direction perpendicular to that path; there must be no intervening tree that obstructs your view. Given the geometrical configuration of the park, please report the number of visible
 

Input
There will be multiple input sets. For each input set, the first line will contain two integers, N and M , ( 0 < N, M <=100000 ), separated by a space. N is the number of trees, and M is the number of paths.

The next N lines each contain two space-separated integers, X and Y , specifying the coordinates of a tree. X and Y may be any 32-bit integers.

The next M lines each describe a path (a vertical or horizontal line). They have the form x = K or y = K , with no spaces. K may be any 32-bit integer. x and y will be lower case.

End of the input is signified by a line with two space-separated 0's.
 

Output
For each input set, print a single line containing one integer, specifying the number of visible trees. There should be no blank lines between outputs.
 

Sample Input
  
  
6 3 -1 3 4 2 6 2 6 3 6 4 4 3 x=0 y=-1 y=5 1 2 2 3 x=5 y=5 0 0
 

Sample Output
  
  
5 1
 

Author
1004
 

Source
 

Recommend

gaojie


关于这道题,可以分别看某个点是否可以通过x=几的某条线看到,或者是否可以通过y=几的某条线看到,以上是通过f_isSeen这个函数来判断的,具体是通过迭代来实现,当判断是否可以通过x=几来判断时,先把x=这些线按照数值从小到大排序,再将所有的点按照y坐标分组,再按照x坐标从小到大排序,接着在每组中循环的条件时每遍历组中的一个点时,确保当前遍历的是上一个点之后的第一条线,在这种情况下,再根据不同的情况判断能不能通过这条线看到,当然还要注意具体的细节。


已ac的代码:


#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define N 100010
#define M 100010
#define C 100

struct s_node{
    int zb[2];
    int id;
};
s_node a_node[N];
int isSeen[N];
int a_x[M];
int a_y[M];
s_node a_node_temp[N];

int getInt(char *c){
    int num=0;

    for(int i=(c[2]=='-'?3:2);c[i]!='\0';i++){
        num=num*10+c[i]-'0';
    }
    if(c[2]=='-'){
        num=-num;
    }

    return num;
}

bool cmp(int a,int b){
    return a<b;
}

bool cmp_x(s_node a,s_node b){
    if(a.zb[1]!=b.zb[1]){
        return a.zb[1]<b.zb[1];
    }
    else{
        return a.zb[0]<b.zb[0];
    }
}

bool cmp_y(s_node a,s_node b){
    if(a.zb[0]!=b.zb[0]){
        return a.zb[0]<b.zb[0];
    }
    else{
        return a.zb[1]<b.zb[1];
    }
}

void f_isSeen(int *a_temp,int num_temp,int z_id,int n){
    int a_node_temp_num;

    for(int i=0;i<n;i++){
        a_node_temp_num=0;
        a_node_temp[a_node_temp_num++]=a_node[i];
        for(i++;i<n&&a_node[i].zb[1-z_id]==a_node[i-1].zb[1-z_id];i++){
            a_node_temp[a_node_temp_num++]=a_node[i];
        }
        i--;

        for(int j=0,k=0;j<a_node_temp_num;j++){
            if(a_node_temp[j].zb[z_id]>a_temp[k]){
                isSeen[a_node_temp[j].id]=true;

                int isBreak=0;
                for(;k<num_temp;k++){
                    if(a_node_temp[j].zb[z_id]<a_temp[k]){
                        isBreak=1;
                        break;
                    }
                }
                if(isBreak==0){
                    break;
                }
            }
            else{
                if(j<a_node_temp_num-1&&a_node_temp[j+1].zb[z_id]>a_temp[k]){
                    isSeen[a_node_temp[j].id]=true;
                }
                else if(j==a_node_temp_num-1){
                    isSeen[a_node_temp[j].id]=true;
                }
            }
        }
    }

    return;
}

int main(){
    int n,m;
    char c[C];
    int x_num,y_num;

    while(scanf("%d%d",&n,&m)!=EOF&&(n!=0||m!=0)){
        x_num=0;
        y_num=0;
        memset(isSeen,false,sizeof(isSeen));
        for(int i=0;i<n;i++){
            scanf("%d%d",&a_node[i].zb[0],&a_node[i].zb[1]);
            a_node[i].id=i;
        }
        for(int i=0;i<m;i++){
            scanf("%s",c);
            if(c[0]=='x'){
                a_x[x_num++]=getInt(c);
            }
            else{
                a_y[y_num++]=getInt(c);
            }
        }
        sort(a_x,a_x+x_num,cmp);
        sort(a_y,a_y+y_num,cmp);

        sort(a_node,a_node+n,cmp_x);
        f_isSeen(a_x,x_num,0,n);
        sort(a_node,a_node+n,cmp_y);
        f_isSeen(a_y,y_num,1,n);

        int num=0;
        for(int i=0;i<n;i++){
            if(isSeen[i]==true){
                num++;
            }
        }

        printf("%d\n",num);
    }

    return 0;
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值