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

36 篇文章 0 订阅
16 篇文章 0 订阅

题目链接

思路:

我一直有个问题不明白,我中等的用线段树水过了为什么我把中等的交到简单就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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Marcus-Bao

万水千山总是情,只给五角行不行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值