HDU 5925 Coconuts 【离散化+BFS】 (2016CCPC东北地区大学生程序设计竞赛)

67 篇文章 0 订阅
63 篇文章 0 订阅

Coconuts

Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 524    Accepted Submission(s): 151


Problem Description
TanBig, a friend of Mr. Frog, likes eating very much, so he always has dreams about eating. One day, TanBig dreams of a field of coconuts, and the field looks like a large chessboard which has R rows and C columns. In every cell of the field, there is one coconut. Unfortunately, some of the coconuts have gone bad. For sake of his health, TanBig will eat the coconuts following the rule that he can only eat good coconuts and can only eat a connected component of good coconuts one time(you can consider the bad coconuts as barriers, and the good coconuts are 4-connected, which means one coconut in cell (x, y) is connected to (x - 1, y), (x + 1, y), (x, y + 1), (x, y - 1).

Now TanBig wants to know how many times he needs to eat all the good coconuts in the field, and how many coconuts he would eat each time(the area of each 4-connected component).
 

Input
The first line contains apositiveinteger T( T10 ) which denotes the test cases. T test cases begin from the second line. In every test case, the first line contains two integers R and C,  0<R,C109  the second line contains an integer n, the number of bad coconuts,  0n200  from the third line, there comes n lines, each line contains two integers,  xi  and  yi , which means in cell( xi,yi ), there is a bad coconut.

It is guaranteed that in the input data, the first row and the last row will not have bad coconuts at the same time, the first column and the last column will not have bad coconuts at the same time.
 

Output
For each test case, output "Case #x:" in the first line, where x denotes the number of test case, one integer k in the second line, denoting the number of times TanBig needs, in the third line, k integers denoting the number of coconuts he would eat each time, you should output them in increasing order.
 

Sample Input
  
  
2 3 3 2 1 2 2 1 3 3 1 2 2
 

Sample Output
  
  
Case #1: 2 1 6 Case #2: 1 8
 

Source
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:   5932  5931  5930  5928  5923 
 

Statistic |  Submit |  Discuss |  Note

题目链接:

  http://acm.hdu.edu.cn/showproblem.php?pid=5925

题目大意:

  R行C列的网格(R,C<=109),有N(N<=200)个障碍,求联通块数量和各个大小(从小到大)。

题目思路:

  【离散化+BFS】

  首先障碍数量很小,所以可以离散化,把一大块没有障碍的网格缩成一个,权值A[i][j]为原先的小网格数。

  缩网格只要以每一个障碍为中心画水平垂直线即可。细节注意一下

  缩完之后有不超过400*400的矩形,暴力枚举一遍联通块,BFS,每个矩形走一次。即可得到各个联通块大小。排序输出即可

  注意0的时候输出两行0.

  (被这题卡了一晚上好气啊,写了随机数据把百度首页的代码全HACK掉了,数据打了崩溃溢出或者WA的。这也能AC吗。最后发现自己多打了一个+1。+1s




//
//by coolxxx
//#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<iomanip>
#include<map>
#include<stack>
#include<queue>
#include<set>
#include<bitset>
#include<memory.h>
#include<time.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//#include<stdbool.h>
#include<math.h>
#pragma comment(linker,"/STACK:1024000000,1024000000")
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(a) ((a)>0?(a):(-(a)))
#define lowbit(a) (a&(-a))
#define sqr(a) ((a)*(a))
#define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define eps (1e-10)
#define J 10000
#define mod 1000000007
#define MAX 0x7f7f7f7f
#define PI 3.14159265358979323
#define N 1004
using namespace std;
typedef long long LL;
double anss;
LL aans;
int cas,cass;
int n,m,lll,ans;
int nc,nn,mm;
LL s[N],r[N],rr[N],a[N][N];
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
bool u[N][N];
struct xxx
{
	int x,y,x1,y1;
}c[N];
bool cmp1(xxx aa,xxx bb)
{
	if(aa.x!=bb.x)return aa.x<bb.x;
	return aa.y<bb.y;
}
bool cmp2(xxx aa,xxx bb)
{
	if(aa.y!=bb.y)return aa.y<bb.y;
	return aa.x<bb.x;
}
void spfa(int sx,int sy)
{
	queue<int>q1,q2;
	int i,j,x,y,xx,yy;
	LL sum;
	q1.push(sx),q2.push(sy);
	u[sx][sy]=1;sum=a[sx][sy];
	while(!q1.empty())
	{
		x=q1.front(),q1.pop();
		y=q2.front(),q2.pop();
		for(j=0;j<4;j++)
		{
			xx=x+dx[j],yy=y+dy[j];
			if(xx<1 || xx>nn || yy<1 || yy>mm || u[xx][yy])continue;
			u[xx][yy]=1;
			q1.push(xx);q2.push(yy);
			sum+=a[xx][yy];
		}
	}
	s[++lll]=sum;
}
void print()
{
	int i;
	if(lll==0){puts("0\n0");return;}
	sort(s+1,s+1+lll);
	printf("%d\n",lll);
	for(i=1;i<=lll;i++)
		printf("%lld%c",s[i],i==lll?'\n':' ');
}
int main()
{
	#ifndef ONLINE_JUDGEW
//	freopen("1.txt","r",stdin);
//	freopen("2.txt","w",stdout);
	#endif
	int i,j,k;
	int x,y,z;
//	init();
//	for(scanf("%d",&cass);cass;cass--)
	for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
//	while(~scanf("%s",s))
//	while(~scanf("%d%d",&n,&m))
	{
		lll=0;mem(u,0);
		printf("Case #%d:\n",cass);
		scanf("%d%d%d",&n,&m,&nc);
		for(i=1;i<=nc;i++)
		{
			scanf("%d%d",&x,&y);
			if(x>n || y>m){i--,nc--;continue;}
			c[i].x=x,c[i].y=y;
		}
		for(i=1;i<N+N;i++)rr[i]=r[i]=1;
		nn=n,mm=m;
		sort(c+1,c+1+nc,cmp1);
		for(i=1;i<=nc;i++)
		{
			if(c[i].x-c[i-1].x>2)
			{
				nn-=c[i].x-c[i-1].x-2;
				c[i].x1=c[i-1].x1+2;
				r[c[i-1].x1+1]*=c[i].x-c[i-1].x-1;
			}
			else c[i].x1=c[i-1].x1+c[i].x-c[i-1].x;
		}
		if(nn!=c[nc].x1)r[c[nc].x1+1]*=nn-c[nc].x1,nn=c[nc].x1+1;
		
		sort(c+1,c+1+nc,cmp2);
		for(i=1;i<=nc;i++)
		{
			if(c[i].y-c[i-1].y>2)
			{
				mm-=c[i].y-c[i-1].y-2;
				c[i].y1=c[i-1].y1+2;
				rr[c[i-1].y1+1]*=c[i].y-c[i-1].y-1;
			}
			else c[i].y1=c[i-1].y1+c[i].y-c[i-1].y;
		}
		if(mm!=c[nc].y1)rr[c[nc].y1+1]*=mm-c[nc].y1,mm=c[nc].y1+1;
		
		for(i=1;i<=nc;i++)u[c[i].x1][c[i].y1]=1;
		for(i=1;i<=nn;i++)
			for(j=1;j<=mm;j++)
				a[i][j]=r[i]*rr[j];
		for(i=1;i<=nn;i++)
		{
			for(j=1;j<=mm;j++)
			{
				if(u[i][j])continue;
				spfa(i,j);
			}
		}
		print();
	}
	return 0;
}
/*
//

//
*/




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值