• LUOGU P1514 引水入城 (bfs)


    传送门

    解题思路

    拉了很长的战线,换了好几种写法终于过了。。首先每个蓄水场一定是对沙漠造成连续一段的贡献,所以可以$bfs$出每种状态,然后做一次最小区间覆盖,但这样的复杂度有点高。就每次只搜那些比左右高的点。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    
    using namespace std;
    const int MAXN = 505;
    const int inf = 0x3f3f3f3f;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    
    int xx[4]={0,0,-1,1},yy[4]={-1,1,0,0};
    int n,m,cnt,h[MAXN][MAXN],ans,num,t;
    int vis[MAXN][MAXN];bool b[MAXN];
    queue<int> Q[3];
    
    struct Data{
        int l,r;
        friend bool operator<(const Data a,const Data b){
            return a.l==b.l?a.r<b.r:a.l<b.l;
        }
    }data[MAXN];
    
    void bfs(int x,int y){
        cnt++;Q[1].push(x);Q[2].push(y);data[cnt].l=inf;t++;vis[x][y]=t;
        while(!Q[1].empty()){
            int i=Q[1].front(),j=Q[2].front();Q[1].pop();Q[2].pop();
            if(i==n) {data[t].l=min(data[t].l,j);data[t].r=max(data[t].r,j);b[j]=1;}
            for(register int k=0;k<=3;k++){
                int ii=xx[k]+i,jj=yy[k]+j;
                if(ii<1 || ii>n || jj<1 || jj>m || vis[ii][jj]==t) continue;
                if(h[i][j]<=h[ii][jj]) continue;vis[ii][jj]=t;
    //            if(ii==n) {data[t].l=min(data[t].l,jj);data[t].r=max(data[t].r,jj);b[jj]=1;}
                Q[1].push(ii);Q[2].push(jj);
            }
        }
    //    if(data[cnt].l==inf) cnt--;
    //    cout<<data[cnt].l<<" "<<data[cnt].r<<endl;
    }
    
    int main(){
        n=rd();m=rd();
        for(register int i=1;i<=n;i++)
            for(register int j=1;j<=m;j++)
                h[i][j]=rd();
        for(int i=1;i<=m;i++) 
            if(h[1][i]>=h[1][i-1] && h[1][i]>=h[1][i+1]) bfs(1,i);
        for(int i=1;i<=m;i++) if(!b[i]) ans++;
        if(ans) {puts("0");printf("%d
    ",ans);return 0;}
        sort(data+1,data+1+cnt);int now=0;data[cnt+1].l=inf;
        for(int i=1;i<=cnt;i++) {
            int mx=0,p=i;if(data[p].r<=now) continue;
            while(data[p].l-now<=1) {mx=max(mx,data[p].r);p++;}
            now=mx;num++;i=p-1;
        }
        puts("1"),printf("%d",num);
        return 0;
    }
    View Code
  • 相关阅读:
    工厂模式
    装饰器模式
    策略模式
    代理模式
    建造者模式
    单例模式
    观察者模式
    JVM运行时数据区
    Export to excel
    C#网络编程(同步传输字符串) Part.2 [转自JimmyZhang博客]
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9769076.html
Copyright © 2020-2023  润新知