zoukankan      html  css  js  c++  java
  • P1514 引水入城

    概述

    首先,这是一道好题,这道题既考查了图论的dfs知识,又考察了区间贪心问题中很典型的区间覆盖问题,着实是一道好题。

    大概思路说明

    我们观察到,只有第一行可以放水库,而第一行在哪里放水库的结果就是直接导致最后一行某些点被覆盖。所以我们只需要找到第一行水库与最后一行被覆盖的关系即可完成决策,中间的行没有意义。我们对于第一行的每一个数进行dfs,可以预处理出所有的区间。然后问题就转化成了用一些区间覆盖一条线段的问题。直接求解即可。

    参考代码

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 505;
    int n, m, high[maxn][maxn], vis[maxn][maxn];
    const int dx[] = {0, 1, 0, -1};
    const int dy[] = {1, 0, -1, 0};
    void dfs(int x, int y) {
    	vis[x][y] = 1;
    	for(int i = 0; i < 4; i++) {
    		int nx = x + dx[i];
    		int ny = y + dy[i];
    		if(nx >= 1 && nx <= m && ny >= 1 && ny <= n &&!vis[nx][ny] && high[nx][ny] < high[x][y]) {
    			dfs(nx, ny);
    		}
    	}
    }
    struct line
    {
    	int left, right, num;
    	bool operator < (const line b) const {
    		if(this->left != b.left) return this->left < b.left;
    		int la = this->right - this->left; 
    		int lb = b.right - b.left;
    		return la > lb;
    	}
    }ls[maxn];
    int main() {
    //	freopen("input.in", "r", stdin);
    	cin >> n >> m;
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= m; j++) 
    			cin >> high[j][i];
    	}
    	int dfn = 0;
    	for(int i = 1; i <= m; i++) { 
    		memset(vis, 0, sizeof(vis)); 
    		dfs(i, 1);         
    		int l = -1, r = -1; 
    		for(int j = 1; j <= m; j++) {
    			if(vis[j][n]) {l = j; break;}
    		}
    		int j;
    		if(l!=-1)for(j = l; j <= m; j++) {
    			if(!vis[j][n]) {r = j - 1; break;}
    		}
    		if(j == m + 1 && l != -1) r = m;
    		if(l != -1 && r != -1) ls[dfn++] = {l, r, i};
    	} 
    	int s = 1;
    	set<int> ans;
    	set<int> no;
    	while(s <= m) {
    		for(int i = 0; i < dfn; i++) {
    			if(ls[i].left <s ) ls[i].left = s;
    			if(ls[i].left > ls[i].right) ls[i] = {maxn, maxn, maxn};
    		}
    		sort(ls, ls+dfn);
    		if(ls[0].left == maxn) { 						//没有可用的区间 
    			for(int i = s; i <= m; i++) no.insert(i);
    			break;
    		}
    		if(ls[0].left!=s) {
    			for(int i = s; i < ls[0].left; i++) no.insert(i);
    		}
    		ans.insert(ls[0].num);
    		s = ls[0].right+1;
    	}
    	if(no.empty()) {
    		cout << 1 << endl << ans.size();
    	}
    	else {
    		cout << 0 << endl << no.size();
    	}
    	return 0;
    }
    
  • 相关阅读:
    随笔
    第一次随笔
    团队战day02-接口
    团队战day01-初步搭建UI
    团队战start-确定项目以及介绍
    团队—易软
    找回感觉的练习
    第五次作业-团队作业-团队组建
    第四次博客作业-结对项目
    java第九次作业
  • 原文地址:https://www.cnblogs.com/gengchen/p/6060692.html
Copyright © 2011-2022 走看看