【NOIP2010】引水入城
这道题从高到低建图,因为有无解的情况,所以从海边可建造蓄水池的地方开始搜索,如果最后一行有搜不到的,那么直接统计一下个数,输出就好。显然搜索不能dfs,深度太大会爆栈啊,所以bfs也可以实现。至于有解的情况,我们考虑一个性质,一个点向下传递,在最后一行能够便利到的点一定是联通的,否则的话是无解的情况,所以我们仍然以每个蓄水池搜索,算出其覆盖最后一行的左右区间,然后dp。
还有一种方法,将每一个蓄水池的覆盖范围看成一条线段,算出区间端点后,对于A,B两个线段,若B的左端点<=A的右端点+1,两个左端点连一条权值为1的边,跑1->m的最短路就行,至于为什么,自己画图体会,很容易理解。
1 #define MAXN 550UL 2 3 #include4 #include 5 #include 6 #include 7 #define MIN(a,b) (a)<(b)?(a):(b); 8 using namespace std; 9 int n,m,cnt,head[MAXN*MAXN]; 10 int H[MAXN][MAXN],ID[MAXN][MAXN],ans,la; 11 bool vis[MAXN*MAXN],flag=0; 12 int f[MAXN]; 13 int Ls[MAXN],Rs[MAXN]; 14 struct Node{ 15 int be,en,to; 16 }eda[1000110]; 17 void Add(int x,int y){ 18 eda[++cnt].be=x; 19 eda[cnt].en=y; 20 eda[cnt].to=head[x]; 21 head[x]=cnt; 22 } 23 struct XS{ 24 int id,h; 25 }D[MAXN*MAXN]; 26 int cop(const XS a,const XS b){ 27 return a.h>b.h; 28 } 29 30 void BFS(int t){ 31 memset(vis,0,sizeof(vis)); 32 queue<int>st; 33 if(t==0)for(int i=1;i<=m;i++) st.push(i),vis[i]=1; 34 else { 35 vis[t]=1; 36 st.push(t); 37 } 38 while(!st.empty()){ 39 int x=st.front(); 40 st.pop(); 41 for(int i=head[x];i;i=eda[i].to){ 42 int y=eda[i].en; 43 if(!vis[y]){ 44 vis[y]=1; 45 st.push(y); 46 } 47 } 48 } 49 } 50 int main(){ 51 freopen("flow.in","r",stdin); 52 freopen("flow.out","w",stdout); 53 scanf("%d%d",&n,&m); 54 for(int i=1;i<=n;i++){ 55 for(int j=1;j<=m;j++){ 56 scanf("%d",&H[i][j]); 57 ID[i][j]=(i-1)*m+j; 58 } 59 } 60 for(int i=1;i<=n;i++){ 61 for(int j=1;j<=m;j++){ 62 if(H[i][j]>H[i-1][j]&&i>1) Add(ID[i][j],ID[i-1][j]); 63 if(H[i][j]>H[i+1][j]&&i 1][j]); 64 if(H[i][j]>H[i][j-1]&&j>1) Add(ID[i][j],ID[i][j-1]); 65 if(H[i][j]>H[i][j+1]&&j 1]); 66 } 67 } 68 BFS(0); 69 bool ok=0; int lr=0; 70 for(int i=1;i<=m;i++){ 71 if(!vis[ID[n][i]]){ 72 ok=1; 73 lr++; 74 } 75 } 76 if(ok){ 77 printf("0\n%d",lr); 78 return 0; 79 } 80 else{ 81 for(int i=1;i<=m;i++){ 82 Ls[i]=m+1; 83 Rs[i]=0; 84 BFS(i); 85 for(int j=1;j<=m;j++){ 86 if(vis[ID[n][j]]){ 87 if(j j; 88 if(j>Rs[i]) Rs[i]=j; 89 } 90 } 91 } 92 memset(f,30,sizeof(f)); 93 f[0]=0; 94 for(int i=1;i<=m;i++){ 95 // printf("%d %d\n",Ls[i],Rs[i]); 96 for(int j=1;j<=m;j++){ 97 if(Ls[j]<=i&&Rs[j]>=i){ 98 f[i]=MIN(f[i],f[Ls[j]-1]+1); 99 } 100 } 101 } 102 printf("1\n%d",f[m]); 103 } 104 getchar(); getchar(); 105 }
posted @
2015-10-09 20:18 Lenicodes 阅读(
...) 评论(
...) 编辑 收藏