• 题解 U23217 【yizimi数字岛屿探险】


    题目链接:https://www.luogu.org/problemnew/show/U23217

    题目

    题目背景

    yizimi的宝藏是数学的奥秘……

    (待完善正解,将来可能会SPJ)

    题目描述

    yizimi在一个岛上降落,他有一个遥感器,显示他所在的坐标x,y,显示了n * m的地图:地图上显示0,则此坐标位置为海洋,地图上显示1~9,则为海拔为显示数字的陆地。

    yizimi发现周围有许多岛屿,包括他自己所在的岛屿,不过他去不了除自己所在岛屿以外的地方。他要寻求的宝藏是他可以去到的所有坐标位置的海拔的乘积,取模100007。

    不过他还想知道他所在的岛屿的面积与所给地图的中有几个岛屿。

    输入输出格式

    输入格式:

    第1行:n,m 地图行数列数

    第2~n+1行:为m个用空格隔开的数字,代表各地海拔。

    第n+2行:x,y yizimi所在第x行,第y列

    输出格式:

    第一行:所在岛屿面积(每个点3分)

    第二行:岛屿个数(每个点3分)

    第三行:yizimi的数字宝藏(每个点4分)

    说明

    对于100%的数据:2<=n,m<=1000

    保证yizimi跳伞不会跳到海里去

    题目分析

    首先,要注意这道题

    有三问!!!!!!

    第一问是一道很简单的连通块的问题,通过DFS。

    第二问是一个关于染色的问题,要染几种颜色才能染完除0外的所有点。

    第三问是第一问的升级版,只是把计数变为了数字乘积而已。

    所以,此题的重点就是在搜索上。

    本道题DFS与BFS都适用。本体街使用的是DFS。

    具体实现

    求简单的连通块

    这个说实话不用多讲,用DFS,枚举每一个方向的可行性,进行下一步扩展,在扩展过程中标记、计数、计算乘积。

    inline void dfs1(int x,int y){
    	for(int i=1;i<=4;i++){
        	int nx=x+dx[i],ny=y+dy[i];
    		if(nx>n || nx<1 || ny>m || ny<1)
    			continue;
    		if(a[nx][ny]>0 && !bb[nx][ny]){
    			ans1++;
    			ans2=(ans2*a[nx][ny])%mod;
    			//cout<<ans2<<"
    ";
    			bb[nx][ny]=true;
    			dfs1(nx,ny);
    		}
    	}
    }
    

    求连通块的个数

    就是枚举所有点所在的连通块,用一个负数标记,每次把大于0的坐标及其连通块染色,继续枚举。

    枚举

    	int color=0;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			if(b[i][j]>0)
    				color--,bbb[i][j]=true,b[i][j]=color,dfs2(i,j,color);
    

    染色

    inline void dfs2(int x,int y,int color){
    	for(int i=1;i<=4;i++){
    		if(nx<=n && nx>=1 && ny<=m && ny>=1 && b[nx][ny]>0){
    			b[nx][ny]=color;
    			bbb[nx][ny]=true;
    			dfs2(nx,ny,color);
    		}
    	}
    }
    

    完整代码

    依然有自己的代码特点

    define狂魔

    中间注释是测试代码用的。

    #include<bits/stdc++.h>
    using namespace std;
    #define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
    #define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
    #define mn 1010
    #define nx x+dx[i]
    #define ny y+dy[i]
    #define inf 1<<30
    #define mod 100007
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch>'9'||ch<'0'){if(ch=='-')f=-f;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    int a[mn][mn],b[mn][mn];
    bool bb[mn][mn],bbb[mn][mn];
    int n,m,startx,starty,ans1,ans2;
    const int dx[5]={0,0,0,-1,1};
    const int dy[5]={0,-1,1,0,0};
    inline void dfs1(int x,int y){
    	go(i,1,4,1){
    		if(nx>n || nx<1 || ny>m || ny<1)
    			continue;
    		if(a[nx][ny]>0 && !bb[nx][ny]){
    			ans1++;
    			ans2=(ans2*a[nx][ny])%mod;
    			//cout<<ans2<<"
    ";
    			bb[nx][ny]=true;
    			dfs1(nx,ny);
    		}
    	}
    }
    inline void dfs2(int x,int y,int color){
    	go(i,1,4,1){
    		if(nx<=n && nx>=1 && ny<=m && ny>=1 && b[nx][ny]>0){
    			b[nx][ny]=color;
    			bbb[nx][ny]=true;
    			dfs2(nx,ny,color);
    		}
    	}
    }
    int main(){
    	//freopen("xiaodao001.in","r",stdin);
    	//freopen("xiaodao001.out","w",stdout);
    	memset(a,0,sizeof(a));
    	memset(b,0,sizeof(b));
    	memset(bb,0,sizeof(bb));
    	n=read(),m=read();
    	//cout<<n<<" "<<m<<"
    ";
    	go(i,1,n,1)
    		go(j,1,m,1)
    			b[i][j]=a[i][j]=read();
    	startx=read(),starty=read();
    	/*
    	cout<<n<<" "<<m<<"
    ";
    	go(i,1,n,1){
    		go(j,1,m,1)
    			cout<<a[i][j]<<" ";
    		cout<<"
    ";
    	}
    	cout<<startx<<" "<<starty<<"
    ";
    	*/
    	bb[startx][starty]=true; 
    	ans1++,ans2=a[startx][starty];
    	dfs1(startx,starty);
    	int color=0;
    	go(i,1,n,1)
    		go(j,1,m,1)
    			if(b[i][j]>0)
    				color--,bbb[i][j]=true,b[i][j]=color,dfs2(i,j,color);
    	cout<<ans1<<"
    "<<-color<<"
    "<<ans2<<"
    ";
    	/*go(i,1,n,1){
    		go(j,1,m,1)
    			cout<<b[i][j]<<" ";
    		cout<<"
    ";
    	}*/
    	return 0;
    }
    
    NOIP2018并不是结束,而是开始
  • 相关阅读:
    学生管理系统后感
    数据库是什么鬼,怎么连接,怎么搞
    nIce 不看会后悔的o!
    那些年披巾斩浪的数据库
    day82
    day81
    day80
    day79
    day78
    day77
  • 原文地址:https://www.cnblogs.com/yizimi/p/10056220.html
Copyright © 2020-2023  润新知