[NOIP 2010] 引水入城

news/2024/7/8 6:15:01

搜索+贪心。

参考博客:http://blog.sina.com.cn/s/blog_8442ec3b0100xib1.html

主要是要看出来,如果有解的话,每个沿湖城市能够流到的范围是连续的区间...然后1遍dfs判断有无解,2遍确定区间,最后排序贪心。

直觉上来说,如果流到的区域中间是断的,那么中间的地势一定比两边高,从其他地方也流不到。

(理论上是应该bfs的= =)


#include <cstdio>
#include <algorithm>
#include <cstring>
#include <utility>
using namespace std;

#define tr(x) printf(#x),putchar('\n')
typedef pair<int, int> P;
const int MAXN = 600, dir[] = {0, 0, 1, -1}, INF = 0x3f3f3f3f;
int H[MAXN][MAXN], vis[MAXN][MAXN], cnt, M, N;
P r[MAXN];	//第一行每个城市可以流到的范围 

void dfs(int x, int y){
	vis[x][y] = 1;
	if(x == N - 1){
		++cnt;
	}
	for(int i = 0; i < 4; ++i){
		int dx = x + dir[i], dy = y + dir[3-i];
		if(0 <= dx && dx < N && 0 <= dy && dy < M && !vis[dx][dy] && H[dx][dy] < H[x][y]){
			dfs(dx, dy);
		}
	}
}

void dfsL(int s, int x, int y){
	vis[x][y] = 1;
	if(x == 0){
		r[y].first = s;
	}
	for(int i = 0; i < 4; ++i){
		int dx = x + dir[i], dy = y + dir[3-i];
		if(0 <= dx && dx < N && 0 <= dy && dy < M && !vis[dx][dy] && H[dx][dy] > H[x][y]){
			dfsL(s, dx, dy);
		}
	}
}

void dfsR(int s, int x, int y){
	vis[x][y] = 1;
	if(x == 0){
		r[y].second = s;
	}
	for(int i = 0; i < 4; ++i){
		int dx = x + dir[i], dy = y + dir[3-i];
		if(0 <= dx && dx < N && 0 <= dy && dy < M && !vis[dx][dy] && H[dx][dy] > H[x][y]){
			dfsR(s, dx, dy);
		}
	}
}

int main(){
	freopen("in.txt", "r", stdin);
	scanf("%d%d", &N, &M);
	for(int i = 0; i < N; ++i){
		for(int j = 0; j < M; ++j){
			scanf("%d", &H[i][j]);
		}
	}
	

	for(int i = 0; i < M; ++i){
		if(!vis[0][i]) dfs(0, i);
	}
	if(cnt < M){
		printf("0\n%d\n", M - cnt);
		return 0;
	}

//======================================	
	for(int i = 0; i < M; ++i){
		r[i].first = INF;
	}
	memset(vis, 0, sizeof(vis));
	for(int i = 0; i < M; ++i){
		if(!vis[N - 1][i]){
			dfsL(i, N-1, i);
		}
	}
	memset(vis, 0, sizeof(vis));
	for(int i = M-1; i >= 0; --i){
		if(!vis[N - 1][i]){
			dfsR(i, N-1, i);
		}
	}

	sort(r, r + M);
	
	int ans = 0, nowr = -1, maxr, i = 0;
	while(i < M && nowr < M - 1){
		maxr = -1;
		while(i < M && r[i].first <= nowr + 1){
			maxr = max(maxr, r[i].second);
			++i;
		}
		nowr = maxr;
		++ans;
	}
	
	printf("1\n%d\n", ans);
	
	return 0;
}


转载于:https://www.cnblogs.com/will7101/p/6506690.html


http://www.niftyadmin.cn/n/666896.html

相关文章

数值转换

对于Number()和paerseInt()"a1231" 两者都是NANnull 前者为0&#xff0c;后者为 NANundefined 两者都是NAN空字符串 前者为0&#xff0c;后者为NANBoolean值 前者为0/1&#xff0c;后者为NAN转载于:https://www.cnbl…

现代女性的半糖主义ZT

我要对爱坚持半糖主义&#xff0c;永远让你觉得意犹未尽&#xff0c;若有似无的甜才不会觉得腻。我要对爱坚持半糖主义&#xff0c;真心不用天天黏在一起……”这一串时下流行于世的歌词&#xff0c; 正挑战着中国女性以爱人为中心的传统观念。与此同时&#xff0c;半糖主义也正…

启动MySQL服务

验证 MySQL 成功安装后&#xff0c;用户需要启动 MySQL 数据库服务并登录。 下面介绍启动MySQL服务&#xff0c;具体操作步骤如下&#xff1a; 步骤 1)&#xff1a;在桌面上右击“此电脑”→“管理”命令&#xff0c;如图所示。 步骤 2)&#xff1a;弹出“计算机管理”对话框…

解决IE中div不居中的问题(尤其IE5)

最近布局时遇到了一个问题&#xff0c;就是如何设置div居中&#xff1f;通过查找资料终于找到了解决方案&#xff0c;只需要把要居中的div外嵌套一个div&#xff0c;设置其“text-align:center;”&#xff0c;然后设置要居中的div为“margin-left:auto;margin-right:auto;”提示…

Android图表库MPAndroidChart(十二)——来点不一样的,正负堆叠条形图

Android图表库MPAndroidChart(十二)——来点不一样的&#xff0c;正负堆叠条形图 接上篇&#xff0c;今天要说的&#xff0c;和上篇的类似&#xff0c;只是方向是有相反的两面&#xff0c;我们先看下效果 实际上这样就导致了我们的代码是比较类似的&#xff0c;先来看下我们的基…

MySQL安装教程,包含所有平台(图解)

现在作为服务器的操作系统一般有两种&#xff0c;分别是 Windows Server 和 Linux&#xff0c;这里我们分别介绍在 Windows 下和 Linux 下安装 MySQL 的具体操作步骤。 在 Windows 系统上安装MySQL Windows 平台下提供两种安装 MySQL 的方式&#xff1a; MySQL 二进制分发版&…

android 围绕中心旋转动画

本文主要介绍Android中如何使用rotate实现图片不停旋转的效果。Android 平台提供了两类动画&#xff0c;一类是 Tween 动画&#xff0c;即通过对场景里的对象不断做图像变换(平移、缩放、旋转)产生动画效果&#xff1b;第二类是 Frame 动画&#xff0c;即顺序播放事先做好的图像…

登录MySQL数据库

用户启动了MySQL服务&#xff0c;便可以通过客户端登录MySQL数据库。 登录MySQL数据库的具体操作步骤如下&#xff1a; 步骤 1)&#xff1a;单击“开始”→“Windows 系统”→“命令提示符”&#xff0c;如图所示。 步骤 2)&#xff1a;打开命令行提示符界面&#xff0c;输入命…