zoukankan      html  css  js  c++  java
  • [CF 316F3]Suns and Rays解题报告

    作者注

    图片来自



    题目大意

    给出一张位图,是太阳和周围的光芒,像这样:

    问有多少个太阳,并统计每个太阳周围的光线数量,排序后输出。
    图的规模是1600*1600,光线的宽度<=3.保证太阳不会太小,光线也不会太短。

    题解

    这题挺有意思。
    首先将白色“收缩”:如果一个点的周围有黑色,就将它变成黑的。重复若干次。


    就变成了这样。

    然后“扩张”,即逆操作:若周围有白的就把它变成白的。


    (注意每个白色区域都变大了)

    我们可以在这张图中找出所有太阳的“核心部分”,并给它们标号。

    用原图减掉这张图,得到:



    这样就把所有的光线独立了出来。对它们进行floodfill即可。

    注意,最后可能有一些小块,判断一下,如果规模太小就不认为是光线即可。

    代码


    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int DIR_NUM=4;
    const int SIZEH=1610,SIZEC=100010;
    int H,W;
    int C;//核心数量
    int board[SIZEH][SIZEH];
    int core[SIZEH][SIZEH];
    int sun[SIZEH][SIZEH];
    int raynum[SIZEC]={0};
    int dx[]={0,0,1,-1,1,1,-1,-1},dy[]={1,-1,0,0,1,-1,1,-1};
    void print(int s[SIZEH][SIZEH]){
    	for(int i=0;i<H;i++){
    		for(int j=0;j<W;j++){
    			if(s[i][j]==-1) printf("-");
    			else printf("%d",s[i][j]);
    		}
    		printf("
    ");
    	}
    }
    int nowtot=0;
    int DFS_ray(int x,int y){
    	sun[x][y]=-1;
    	nowtot++;
    	int ans=0;
    	for(int d=0;d<DIR_NUM;d++){
    		int x1=x+dx[d],y1=y+dy[d];
    		if(0<=x1&&x1<H&&0<=y1&&y1<W){
    			if(sun[x1][y1]>0) ans=sun[x1][y1];
    			else if(sun[x1][y1]==0){
    				int tp=DFS_ray(x1,y1);
    				if(tp) ans=tp;
    			}
    		}
    	}
    	return ans;
    }
    void Find_Ray(void){
    	for(int i=0;i<H;i++){
    		for(int j=0;j<W;j++){
    			if(sun[i][j]==0){
    				nowtot=0;
    				int t=DFS_ray(i,j);
    				if(nowtot>=5) raynum[t]++;
    			}
    		}
    	}
    }
    void DFS_core(int x,int y,int col){
    	core[x][y]=col;
    	for(int d=0;d<DIR_NUM;d++){
    		int x1=x+dx[d],y1=y+dy[d];
    		if(0<=x1&&x1<H&&0<=y1&&y1<W){
    			if(core[x1][y1]==0) DFS_core(x1,y1,col);
    		}
    	}
    }
    void Find_Core(void){
    	int timer=0;
    	for(int i=0;i<H;i++){
    		for(int j=0;j<W;j++){
    			if(core[i][j]==0){
    				DFS_core(i,j,++timer);
    			}
    		}
    	}
    	C=timer;
    }
    void Background_Spread(int f[SIZEH][SIZEH],int g[SIZEH][SIZEH]){//p向外扩散
    	for(int i=0;i<H;i++){
    		for(int j=0;j<W;j++){
    			g[i][j]=f[i][j];
    			for(int d=0;d<DIR_NUM;d++){
    				int i1=i+dx[d],j1=j+dy[d];
    				if(0<=i1&&i1<H&&0<=j1&&j1<W){
    					if(f[i1][j1]==-1) g[i][j]=-1;
    				}
    			}
    		}
    	}
    }
    void Multiple_Background_Spread(int f[SIZEH][SIZEH],int tim){
    	static int g[SIZEH][SIZEH];
    	for(int i=1;i<=tim;i++){
    		Background_Spread(f,g);
    		memcpy(f,g,sizeof(g));
    	}
    }
    void Sun_Recover(int f[SIZEH][SIZEH],int g[SIZEH][SIZEH]){
    	for(int i=0;i<H;i++){
    		for(int j=0;j<W;j++){
    			g[i][j]=max(f[i][j],board[i][j]);
    			for(int d=0;d<DIR_NUM;d++){
    				int i1=i+dx[d],j1=j+dy[d];
    				if(0<=i1&&i1<H&&0<=j1&&j1<W){
    					if(board[i][j]>=0&&f[i1][j1]>0) g[i][j]=f[i1][j1];
    				}
    			}
    		}
    	}
    }
    void Multiple_Sun_Recover(int f[SIZEH][SIZEH],int tim){
    	static int g[SIZEH][SIZEH];
    	for(int i=1;i<=tim;i++){
    		Sun_Recover(f,g);
    		memcpy(f,g,sizeof(g));
    	}
    }
    void Work(void){
    	int width=3;//三次就能消去所有光束
    	memcpy(core,board,sizeof(core));
    	Multiple_Background_Spread(core,width);
    	Find_Core();
    	memcpy(sun,core,sizeof(sun));
    	Multiple_Sun_Recover(sun,width);
    	Find_Ray();
    	sort(raynum+1,raynum+1+C);
    	printf("%d
    ",C);
    	for(int i=1;i<=C;i++) printf("%d ",raynum[i]);
    	printf("
    ");
    }
    void Read(void){
    	scanf("%d%d",&H,&W);
    	for(int i=0;i<H;i++){
    		for(int j=0;j<W;j++){
    			scanf("%d",&board[i][j]);
    			board[i][j]--;
    		}
    	}
    }
    int main(){
    	//freopen("t1.in","r",stdin);
    	//freopen("t1.out","w",stdout);
    	Read();
    	Work();
    	return 0;
    }
    


  • 相关阅读:
    ASP.NET MVC 部分视图
    IIS7.5安全配置研究
    微信公众号抢现金红包活动的核心代码分析(asp.net C#)
    [Android] hid设备按键流程简述
    [Android] AudioTrack::start
    [Android] createTrack_l
    [Android] 输入系统(三):加载按键映射
    [Android] 获取音频输出getOutput
    [Android] AudioTrack实例
    [Android] 输入系统(二)
  • 原文地址:https://www.cnblogs.com/wmdcstdio/p/7554243.html
Copyright © 2011-2022 走看看