引水入城
作者:互联网
引水入城
挺好的题..
首先可以思考到将第一行每一个点作为bfs的起点找出他能到的干旱地区,之后就想着状压...结果发现500根本压不下来...
那我们就要找点性质让我们可以DP....
之后就知道了每一个水库覆盖着干旱地区一定是连续的区间,因为如果连续,就一定会有交叉,之后就可以被一个水库代替...
这样我们就可以轻松DP了....
dp貌似可以线段树优化,管它呢,反正总复杂度O(n^3)了,就暴力DP吧..
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=510; int h[N][N],n,m,dx[5]={-1,1,0,0},dy[5]={0,0,-1,1},f[N]; struct node{int l,r;}a[N]; bool vis[N][N]; inline int read() { int x=0,ff=1; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*ff; } inline bool cmp(node x,node y) {return x.l<y.l;} inline void bfs(int x,int y) { queue<pair<int,int> >q; memset(vis,0,sizeof(vis)); if(x==0&&y==0) { for(int i=1;i<=m;++i) { vis[1][i]=1; q.push({1,i}); } } else vis[x][y]=1,q.push({x,y}); while(!q.empty()) { int t1=q.front().first; int t2=q.front().second;q.pop(); for(int i=0;i<4;++i) { int xx=t1+dx[i]; int yy=t2+dy[i]; if(xx<1||xx>n||yy<1||yy>m) continue; if(h[xx][yy]<h[t1][t2]&&!vis[xx][yy]) { vis[xx][yy]=1; q.push({xx,yy}); } } } } int main() { freopen("1.in","r",stdin); n=read();m=read(); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) h[i][j]=read(); bfs(0,0); int cnt=0; for(int i=1;i<=m;++i) if(vis[n][i]) cnt++; if(cnt!=m) {printf("%d\n%d",0,m-cnt);return 0;} for(int i=1;i<=m;++i) { bfs(1,i); for(int j=1;j<=m;++j) if(vis[n][j]) { if(!a[i].l) a[i].l=a[i].r=j; else a[i].r=j; } } sort(a+1,a+m+1,cmp); memset(f,0x3f,sizeof(f)); f[0]=0; for(int i=1;i<=m;++i) { if(a[i].l>=1) for(int j=a[i].l-1;j<a[i].r;++j) f[a[i].r]=min(f[a[i].r],f[j]+1); } printf("%d\n%d",1,f[m]); return 0; }View Code
标签:...,ch,int,引水,vis,isdigit,DP 来源: https://www.cnblogs.com/gcfer/p/12435259.html