微软大楼设计方案 bfs和线段树

来源:互联网 发布:淘宝网客服投诉电话 编辑:程序博客网 时间:2024/06/06 23:16

题目链接

思路:

我一直有个问题不明白,我中等的用线段树水过了为什么我把中等的交到简单就wa了?

对于简单的我们就可以把整个大楼想象成一个图,有楼的地方全部设置为1表示可走,没有的设置为0表示不可走,对于这个50*50的图枚举两个点跑bfs求最短距离即可.

#include<bits/stdc++.h>typedef long long ll;using namespace std;const int maxn = 222;int mp[maxn][maxn];int h[maxn],n,k,m;int a[maxn],b[maxn],book[maxn][maxn]; int go[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};struct node{    int x, y, s;};int solve(int s, int e){node w,z;    queue<node>q;    memset(book,0,sizeof(book));    book[a[s]][b[s]] = 1;    w.x=a[s];    w.y=b[s];    w.s=0;    q.push(w);    while(!q.empty())    {         w = q.front();        q.pop();        if(w.x == a[e] && w.y == b[e]) return w.s;        for(int i = 0; i < 4; i++)        {            int tx = w.x+go[i][0];            int ty = w.y+go[i][1];            if(tx>=1&&ty>=1&&mp[tx][ty]==1)            {                if(book[tx][ty]==1) continue;                book[tx][ty] = 1;                z.x=tx;                z.y=ty;                z.s=w.s+1;                q.push(z);            }        }    }}int main(){    while(~scanf("%d%d", &n, &k))    {int cnt = 0;        memset(mp, 0, sizeof(mp));        for(int i = 1; i <= n; i++)        {            scanf("%d", &h[i]);            for(int j = 1; j <= h[i]; j++)                mp[i][j] = 1;        }        scanf("%d", &m);        for(int i = 1; i <= m; i++)            scanf("%d%d", &a[i], &b[i]);        for(int i = 1; i <= m; i++)            for(int j = i+1; j <= m; j++)                if(solve(i,j)<=k)                    cnt++;        printf("%d\n", cnt);    }    return 0;}


对于这个中等的,我们知道了两个部门的具体位置那么我们怎么看到达的最短距离?我们肯定如果中间的楼可以直接到达肯定直接到达比下到底层在到达省时间,那么我们只需要确定x1----x2两点的最矮的一层楼,可以用线段树来求这个区间的最小值.

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxnn = 222222;int minn=0;struct node{    int l,r;    int m;}t[maxnn*4];struct point{    int x,y;}p[maxnn*4];int a[maxnn], n, k, m;void build(int i,int left,int right){    t[i].l=left,t[i].r=right;    if(left==right)    {        t[i].m=a[left];        return ;    }    int mid=(left+right)>>1;    build(i<<1,left,mid);    build(i<<1|1,mid+1,right);    t[i].m=min(t[i<<1].m,t[i<<1|1].m);}void query(int i,int left,int right){    if(t[i].l==left&&t[i].r==right)    {        minn=min(minn,t[i].m);        return ;    }    int mid=(t[i].l+t[i].r)>>1;    if(left>mid)    {        query(i<<1|1,left,right);    }    else if(right<=mid)    {        query(i<<1,left,right);    }    else    {        query(i<<1,left,mid);        query(i<<1|1,mid+1,right);    }}ll solve(int a,int b){    ll ans=0;    minn=0x3f3f3f3f;    if(p[a].x>p[b].x)        swap(a,b);    if(a==b)    {        ans=fabs(p[a].y-p[b].y);    }    else    {        ans+=p[b].x-p[a].x;        query(1,p[a].x,p[b].x);        ans+=p[b].y-minn;        ans+=p[a].y-minn;    }    return ans;}int main (void){    scanf("%d%d",&n,&k);    for(int i=1; i<=n; ++i)        scanf("%d",&a[i]);    build(1, 1, n);    scanf("%d",&m);    for(int i=1; i<=m; ++i)    scanf("%d%d",&p[i].x,&p[i].y);    ll ans = 0;    for(int i=1; i<=m; ++i)    {        for(int j=i+1; j<=m; ++j)        {            if(solve(i, j) <= k)                ans++;        }    }    printf("%d\n",ans);    return 0;}


阅读全文
0 0
原创粉丝点击