洛谷 1514 (NOIp2010) 引水入城
题目:https://www.luogu.org/problemnew/show/P1514
如果有解,一个第一行的格子能覆盖第n行的一定是一个连续的区间。
因为如果不连续,则有围住了一些第n行的格子却流不过去的情况。这样被围住的格子肯定谁都流不到它。
!!必须加第54行的判断!不然会无限TLE。dfs似乎是爆栈。那bfs为什么也不行?
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N=505; int n,m,a[N][N],ct; int fx[5]={-1,0,0,1},fy[5]={0,-1,1,0}; bool fg[N],vis[N][N]; struct Node{ int l,r; }b[N],q[N]; bool check(int x,int y,int i) { int tx=x+fx[i],ty=y+fy[i]; if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&a[tx][ty]<a[x][y]&&!vis[tx][ty])return true; return false; } void dfs(int x,int y,int rt) { vis[x][y]=1; if(x==n){ fg[y]=1;b[rt].l=min(b[rt].l,y); b[rt].r=max(b[rt].r,y); } for(int i=0;i<4;i++) if(check(x,y,i)) dfs(x+fx[i],y+fy[i],rt); } //void bfs(int rt) //{ // queue<pair<int,int> > qu; // qu.push(make_pair(1,rt));vis[1][rt]=1; // while(qu.size()) // { // int x=qu.front().first,y=qu.front().second; // qu.pop(); // if(x==n){fg[y]=1;b[rt].l=min(b[rt].l,y);b[rt].r=max(b[rt].r,y);} // for(int i=0;i<4;i++) if(check(x,y,i)) // { // vis[x+fx[i]][y+fy[i]]=1; // qu.push(make_pair(x+fx[i],y+fy[i])); // } // } //} bool cmp(Node u,Node v){return u.l==v.l?u.r>v.r:u.l<v.l;} int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&a[i][j]); for(int i=1;i<=m;i++) { if(a[1][i-1]>a[1][i]||a[1][i+1]>a[1][i])continue;//////// memset(vis,0,sizeof vis);vis[1][i]=1; b[i].l=m+1;dfs(1,i,i); } int cnt=0; for(int i=1;i<=m;i++)if(!fg[i])cnt++; if(cnt){ printf("0\n%d",cnt);return 0; } sort(b+1,b+m+1,cmp); for(int i=1;i<=m;i++) { q[++ct]=b[i]; while(b[i].l==b[i+1].l)i++; } q[ct+1].l=m+1; int now=0,cr=1,k=0; while(now<m) { for(;q[cr].l<=now+1;cr++)k=max(k,q[cr].r); now=k;cnt++; } printf("1\n%d",cnt); return 0; }