首页 > 其他分享 >P3456 [POI2007] GRZ-Ridges and Valleys

P3456 [POI2007] GRZ-Ridges and Valleys

时间:2025-01-20 19:00:13浏览次数:1  
标签:Valleys && flag1 int POI2007 GRZ 遍历 dx dy

P3456 [POI2007] GRZ-Ridges and Valleys

背景

本人蒟蒻,只会写 DFS 。本题 BFS 更好

思路

这是一道很明显的搜索题,题目要求我们找到山峰山谷
山峰? 不就是在这个高度周围没有比它跟高的地方
山谷? 不就是在这个高度周围没有比它更矮的地方
因此我们只需要用 \(DFS\) 遍历遇到的所有高度—在遍历的期间查询周围的高度是否有比它高的和比它矮的即可
注意: 各个山峰和山谷之间的高度是不同的!!并不是最高的是山峰最矮的是山谷

实现

在代码实现过程中可能会遇到的问题:
一: 按照正常思路,\(DFS\) 遍历过程中会把已经遍历过的点给赋值成其他值,来防止死递归和多次遍历。但本题在后面的深搜中还需要利用其高度,因此这里给出两种思路:

1. 多开一个布尔类型的数组来储存该节点是否遍历过。
2. 将原本的改成其的负数,在判断高度时加一绝对值即可 (为什么会说这个方法,是因为本人太蒟蒻,没想出方法一,而想出了此方法)

二: 在 \(DFS\) 遍历中每到一个节点就对其上下左右等进行高度的判断,若有比他高的: \(flag1=true\) 若有比他矮的 \(flag2=true\) (初始皆为 \(false\) )
\(DFS\)代码实例:

void dfs(int x,int y){
    a[x][y]=-a[x][y];
    int dx,dy;
    for(int i=-1;i<=1;i++){
        for(int j=-1;j<=1;j++){
            dx=x+i;
            dy=y+j;
            if(dx>=1 && dx<=n && dy>=1 && dy<=n && abs(a[dx][dy])>abs(a[x][y])){
            	flag1=true;
			}
            if(dx>=1 && dx<=n && dy>=1 && dy<=n && abs(a[dx][dy])<abs(a[x][y])){
            	flag2=true;
			}
            if(dx>=1 && dx<=n && dy>=1 && dy<=n && a[dx][dy]==q){
                dfs(dx,dy);
            }
        }
    }
    return;
}

(记得判断越界!!!)
三: 最后在 \(DFS\) 结束后判断
\(1.\)若既有比他高的又有比它矮的,那他啥也不是 \(if\)(\(flag1\) && \(flag2\))
\(1.\)若有比他高的却没有比它矮的,那他就是山谷 \(if\)(\(flag1\) && \(!flag2\))
\(1.\)若有比他矮的却没有比它高的,那他就是山峰 \(if\)(\(!flag1\) && \(flag2\))

注意要特判是否为平地(及高度一致)那么山峰和山谷都是1

代码:

#include<bits/stdc++.h>
using namespace std;
int a[1001][1001];
int ans1,ans2,q;
int n;
bool flag1,flag2,flag;
void dfs(int x,int y){
    a[x][y]=-a[x][y];
    int dx,dy;
    for(int i=-1;i<=1;i++){
        for(int j=-1;j<=1;j++){
            dx=x+i;
            dy=y+j;
            if(dx>=1 && dx<=n && dy>=1 && dy<=n && abs(a[dx][dy])>abs(a[x][y])){
            	flag1=true;
			}
            if(dx>=1 && dx<=n && dy>=1 && dy<=n && abs(a[dx][dy])<abs(a[x][y])){
            	flag2=true;
			}
            if(dx>=1 && dx<=n && dy>=1 && dy<=n && a[dx][dy]==q){
                dfs(dx,dy);
            }
        }
    }
    return;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
    	for(int j=1;j<=n;j++){
    		cin>>a[i][j];
    		a[i][j]+1;
    		if(a[i][j]!=a[1][1]){
    			flag=true;
			}
		} 
    }
    if(!flag){
    	cout<<1<<" "<<1;
    	return 0;
	}
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(abs(a[i][j])!=-a[i][j] ){
            	flag1=flag2=false;
            	q=a[i][j];
                dfs(i,j);
                if(flag1 && !flag2){
                	ans2++;
				}
				else if(!flag1 && flag2){
					ans1++;
				}
            }
        }
    }
    if(ans2==2){
    	cout<<ans1<<" "<<3;
    	return 0;
	}
    cout<<ans1<<" "<<ans2;
    return 0;
}

标签:Valleys,&&,flag1,int,POI2007,GRZ,遍历,dx,dy
From: https://www.cnblogs.com/XichenOC/p/18682325

相关文章

  • 2018多校集训 H. Hills And Valleys
    传送门题意给你一个\(n\leq10^5\)的序列,数字都是0-9,你可以任意翻转一个子区间,问翻转后最长不降子序列的最大长度。题解简略题解:我开始考虑的是\(f_i,j,k\)表示的是翻转\(i\)结尾的区间,翻转区间贡献了最长不降序列中\(j\)到\(k\)的部分,那么只要新加入的数小于\(j\)就可以翻......
  • [POI2007] OSI-Axes of Symmetry 题解
    给出一个多边形,求对称轴数量。考虑对于一个多边形,其是对称的当且仅当对于若干个边(角),其左右的角与边都是对称的。考虑如果我们对于内角构造出一种单射,映射为一个整数,将边映射为它的边长,那么我们按照角,边,角,边,……的顺序将他们加入数组中,能构造出一个长度为\(2n\)的数组,将这个......
  • LeetCode 2210. Count Hills and Valleys in an Array
    原题链接在这里:https://leetcode.com/problems/count-hills-and-valleys-in-an-array/description/题目:Youaregivena 0-indexed integerarray nums.Anindex i ispartofa hill in nums iftheclosestnon-equalneighborsof i aresmallerthan nums[i].......
  • [POI2007] ATR-Tourist Attractions
    [POI2007]ATR-TouristAttractions题目背景EnglishEdition题目描述给出一张有\(n\)个点\(m\)条边的无向图,每条边有边权。你需要找一条从\(1\)到\(n\)的最短路径,并且这条路径在满足给出的\(g\)个限制的情况下可以在所有编号从\(2\)到\(k+1\)的点上停留过。每......
  • POI2007ATR-Tourist Attractions
    最短路#状压dp#滚动优化#POI#Year2007从前\(k\)个跑\(dijksta\),对这\(k\)个点到达的状态状压会MLE,考虑每次转移都只会增加一个状压下的\(1\),按照\(popcount\)分组做滚动//Author:xiaruizeconstintINF=0x3f3f3f3f;constintMOD=1000000007;constin......
  • POI2007TET-Tetris Attack
    POI#Year2007#贪心#树状数组考虑每一对数的最小代价为,将当前的换到最近的下面用树状数组记录中间有几个没有被消掉的//Author:xiaruizeconstintN=2e5+10;intn,m;intla[N];structBIT{ inttr[N]; voidadd(intx,intv) { while(x<=m) { t......
  • POI2007POW-The Flood
    POI#Year2007#并查集#贪心按高度从小到大按顺序考虑每个点,将同样高度的点按顺序全部合并完,然后再遍历这些同样大小的点,如果一个点为关键点且它的联通块中没有抽水机,那么这个位置联通块的最低位置放一个抽水机可以证明这个贪心是最优的//Author:xiaruizeconstintN=1e3......
  • POI2007ODW-Weights
    进制#背包dp#贪心注意到呈倍数的性质,考虑按照倍数转换进制,贪心的选择小的按顺序选择//Author:xiaruizeconstintINF=0x3f3f3f3f3f3f3f3f;constintMOD=1000000007;constintN=2e5+10;intn,m;inta[N],b[N];piis[N];intcnt[N];vector<int>vec;int......
  • [POI2007] [LUOGU P3451]旅游景点 Tourist Attractions
    本题解由于作者太菜在POI及LUOGU上会TLE,该题解主要讲思路,剩下的内存优化请各位大佬自行补充,欢迎评论区讨论本题解运行时间10406ms,空间194584KiB题目描述FGD想从成都去上海旅游。在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情。经过这些城......
  • 3101: *【莫比乌斯反演:练习】gcd(i,j)=k的对数[POI2007]ZAP-Queries
    问题给出\(n,m,k\)(\(1\leqn,m,k\leq10^5\)),求\(\sum\limits_{i=1}^n\sum\limits_{j=1}^m\lbrack\gcd(i,j)=k\rbrack\),即:满足\(1\leqi\leqn\),\(1\leqj\leqm\),且\(\gcd(i,j)=k\)的二元组\((i,j)\)的数量。题解\(\sum\limits_{i=1}......