[NOIP2010]引水入城

搜索水题
但是我还是wa了好几次,把求不能收到水的看成能收到水的了。。。。
大概解法就是先bfs出来所有靠湖的城能波及到的靠沙漠的,然后判断一下行不行,行的话就dp

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int dx[]={0,1,0,-1},dy[]={1,0,-1,0};
int n,m,g[505][505],used[505],now,f[505][505];
bool vis[505][506];
struct RES{int l,r;}res[505];
bool cmp(RES x,RES y) {return x.l<y.l;}
struct Node{int x,y;};queue<Node>q;
inline void bfs(const int x) {
    res[now].l=100000;
    q.push((Node){1,x});vis[1][x]=1;
    while(!q.empty()) {
        const int x=q.front().x,y=q.front().y;q.pop();
        if(x==n) res[now].l=min(res[now].l,y),res[now].r=max(res[now].r,y),used[y]=1;
        for(int d=0;d<4;d++) {
            const int nx=x+dx[d],ny=y+dy[d];
            if(nx>0&&nx<=n&&ny>0&&ny<=m&&g[nx][ny]<g[x][y]&&vis[nx][ny]==false) vis[nx][ny]=true,q.push((Node){nx,ny});
        }
    }
}
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&g[i][j]);
    for(int i=1;i<=m;i++) if(g[1][i-1]<=g[1][i]&&g[1][i+1]<=g[1][i]) memset(vis,0,sizeof vis),++now,bfs(i);
    sort(res+1,res+1+now,cmp);int cnt=0;
    bool flag=0;
    for(int i=1;i<=m;i++) {if(used[i])cnt++;else flag=1;}
    if(flag) {printf("0\n%d",m-cnt);return 0;}
    printf("1\n");
    memset(f,0x3f,sizeof f);
    f[0][0]=0;
    for(int i=1;i<=now;i++) {
        f[i][0]=0;
        for(int j=1;j<=m;j++) {
        f[i][j]=min(f[i-1][j],f[i][j]);
        if(res[i].l<=j) f[i][res[i].r]=min(f[i][res[i].r],f[i][j-1]+1);
        }
    }
    printf("%d\n",f[now][m]);
}

猜你喜欢

转载自www.cnblogs.com/sdfzhsz/p/9641344.html