【洛谷p1902】刺杀大佬(雾)

 

最开始我想这个题,第一眼是棋盘dp,结果超时了,而后打了个dfs,超时超的比dp还狠,最后打了个二分+bfs,终于a了

结论:这个题真恶心,看来心里没点b树(雾)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
struct in
{
    int x,y;
};
queue<in>qwq;
int fx[5]={0,-1,0,1,0},fy[5]={0,0,1,0,-1};
int n,m,l,mid,r,ans,mx=-1000000007,mi=1000000007,mmp[1010][1010],dp[1010][1010];
bool flag[1010][1010];
bool bfs()
{
    memset(flag,0,sizeof(flag));
    while(!qwq.empty())
        qwq.pop();
    for(int i=1;i<=m;i++)
        if(mmp[2][i]<=mid)
            qwq.push((in){2,i}),flag[2][i]=1;//初始化 
    while(!qwq.empty())
    {
        in qaq=qwq.front();
        if(qaq.x==n)//如果能走到最后一行,因为最后一行杀伤力为0,所以自然对答案没有影响 
            return 1; 
        for(int i=1;i<=4;i++)
        {
            if(qaq.x+fx[i]<=1||qaq.y+fy[i]<1||qaq.y+fy[i]>m)//防止数组越界 
                continue;
            if(mmp[qaq.x+fx[i]][qaq.y+fy[i]]<=mid&&!flag[qaq.x+fx[i]][qaq.y+fy[i]])//如果没走过而且这个点比答案小 
                qwq.push((in){qaq.x+fx[i],qaq.y+fy[i]}),flag[qaq.x+fx[i]][qaq.y+fy[i]]=1;//加入队列 
        }
        qwq.pop();
    }
    return 0;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&mmp[i][j]);
    for(int i=2;i<=n-1;i++)
        for(int j=1;j<=m;j++)
            mx=max(mx,mmp[i][j]),mi=min(mi,mmp[i][j]);//预处理下最大最小值,便于下面二分 
    l=mi,r=mx;
    while(l<r)
    {
        mid=l+r>>1;
        if(bfs())//返回真则说明答案偏大,可以去掉一些较大的点 
            r=mid;
        else//否则说明答案太小 
            l=mid+1;
    }
    printf("%d",l);
}

 

posted @ 2017-10-21 18:47  那一抹落日的橙  阅读(173)  评论(0编辑  收藏  举报