社区讨论

求助!!复杂度为O(n*n*m+n) 然而T了8个点

P1514[NOIP 2010 提高组] 引水入城参与者 3已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@mi7xxuj1
此快照首次捕获于
2025/11/21 05:26
4 个月前
此快照最后确认于
2025/11/21 05:26
4 个月前
查看原帖
CPP
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 510;

int a[N][N], vis[N][N], fin[N], tmp[N], n, m, cnt = 0;;
int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, -1, 1};

struct node {
	int x, y;
};
struct segment {
	int l, r, f;
} seg[N];

bool cmp(segment p, segment q) {
	return p.r > p.r;
}

void bfs(int s) {
	memset(vis, 0, sizeof(vis));
	memset(tmp, 0, sizeof(tmp));
	queue<node> q;
	q.push((node) {1, s});
	vis[1][s] = 1;
	while(q.size()) {
		int x = q.front().x, y = q.front().y;
		q.pop();
		if(x == n) fin[y]= 1;// 该节点可灌溉
		for(int i = 0; i < 4; i++) {
			int nx = x+dx[i], ny = y+dy[i];
			if(a[nx][ny]<a[x][y] && (nx>0&&nx<=n&&ny>0&&ny<=m) && !vis[nx][ny]) {
				q.push((node) {nx, ny});
				vis[nx][ny] = 1;
			}
		}
	}
	for(int i = 1; i <= m+1; i++) {//保存宽搜结果
		if(!a[n][i-1] && a[n][i]) {
			seg[++cnt].l = i;
			seg[cnt].f = s;
		}
		if(!a[n][i] && a[n][i-1]) {
			seg[cnt].r = i-1;
		}
	}
	return;
}

int main() {
	cin >> n >> m;
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			cin >> a[i][j];
		}
	}
	for(int i = 1; i <= m; i++) bfs(i);//宽搜求出每个点可以灌溉的区间

	int flag = 0;
	for(int i = 1; i <= m; i++)
		if(!fin[i]) flag++;
	if(flag) {
		cout << 0 << endl << flag << endl;
		return 0;
	} else cout << 1 << endl;
	//最少线段覆盖
	sort(seg+1, seg+cnt+1, cmp);
	seg[++cnt].l = 555;
	int s = 1, ans = 0;
	for(int i = 1; i <= cnt; i++){
	    if(seg[i].l > s){
	        --i;
	        ans++;
	        s = seg[i].r;
	    }
	    if(s >= m) break;
	}
	cout << ans << endl;
	return 0;
}

回复

2 条回复,欢迎继续交流。

正在加载回复...