2420. Icy Perimeter

2420. Icy Perimeter

(File IO): input:perimeter.in output:perimeter.out
时间限制: 1000 ms 空间限制: 262144 KB 具体限制
Goto ProblemSet


题目描述

Farmer John要开始他的冰激凌生意了!他制造了一台可以生产冰激凌球的机器,然而不幸的是形状不太规则,所以他现在希望优化一下这台机器,使其产出的冰激凌球的形状更加合理。
机器生产出的冰激凌的形状可以用一个N×N(1≤N≤1000)的矩形图案表示,例如:
每个’.‘字符表示空的区域,每个’#‘字符表示一块1×1的正方形格子大小的冰激凌。
不幸的是,机器当前工作得并不是很正常,可能会生产出多个互不相连的冰激凌球(上图中有两个)。一个冰激凌球是连通的,如果其中每个冰激凌的正方形格子都可以从这个冰激凌球中其他所有的冰激凌格子出发重复地前往东、南、西、北四个方向上相邻的冰激凌格子所到达。
Farmer John想要求出他的面积最大的冰激凌球的面积和周长。冰激凌球的面积就是这个冰激凌球中’#'的数量。如果有多个冰激凌球并列面积最大,他想要知道其中周长最小的冰激凌球的周长。在上图中,小的冰激凌球的面积为2,周长为6,大的冰激凌球的面积为13,周长为22。
注意一个冰激凌球可能在中间有“洞”(由冰激凌包围着的空的区域)。如果这样,洞的边界同样计入冰激凌球的周长。冰激凌球也可能出现在被其他冰激凌球包围的区域内,在这种情况下它们计为不同的冰激凌球。例如,以下这种情况包括一个面积为1的冰激凌球,被包围在一个面积为16的冰激凌球内:
同时求得冰激凌球的面积和周长十分重要,因为Farmer John最终想要最小化周长与面积的比值,他称这是他的冰激凌的“冰周率”。当这个比率较小的时候,冰激凌化得比较慢,因为此时冰激凌单位质量的表面积较小。

输入

输入的第一行包含N,以下N行描述了机器的生产结果。其中至少出现一个’#'字符。

输出

输出一行,包含两个空格分隔的整数,第一个数为最大的冰激凌球的面积,第二个数为它的周长。如果多个冰激凌球并列面积最大,输出其中周长最小的那一个的信息。

样例输入

6
##....
....#.
.#..#.
.#####
...###
....##

样例输出

13 22

题目没什么好讲的,就是一道搜索模板题。
我考试时用了dfs,但是有一个点没过,听网上大佬们说,是爆栈了。只怨我才疏学浅,还是不懂
最后通过特判,才将dfs改对。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int dx[8]={-1,1,0,0};
const int dy[8]={0,0,-1,1};
int n,ans,ans1,maxn,sum,maxc,c[1010][1010];
char a[1010][1010];
bool f[1010][1010];
void input()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	{
		char s;
		cin>>s;
		if(s=='#') sum++;  //特判全是‘#’
		a[i][j]=(s=='.')?0:1;	
	}
}
void dfs(int x,int y)
{
	for(int i=0;i<4;i++)
	{
		int nx=x+dx[i],ny=y+dy[i];
		if(nx>=1&&nx<=n&&ny>=1&&ny<=n&&!f[nx][ny]&&a[nx][ny])
		{
			f[nx][ny]=1;
			ans++;
			ans1+=c[nx][ny];
			dfs(nx,ny);
		}
	}
}
void zc()
{
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(a[i][j])
			{
				if(!a[i-1][j]) c[i][j]++;
				if(!a[i+1][j]) c[i][j]++;
				if(!a[i][j-1]) c[i][j]++;
				if(!a[i][j+1]) c[i][j]++;	
			}
}
int main()
{
	fre(perimeter);
	input();
	if(sum==n*n)
	{
		printf("%d %d\n",sum,4*n);
		return 0;
	}
	zc();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(a[i][j]&&!f[i][j])
			{
				ans=1,ans1=c[i][j];
				f[i][j]=1;
				dfs(i,j);
				if(maxn<ans) maxn=ans,maxc=ans1;	
				if(maxn==ans) maxc=min(maxc,ans1);
			}
	printf("%d %d\n",maxn,maxc);
	return 0;
}

bfs就没问题,也是个模板。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;

struct node {int x,y;}q[1000010];
const int dx[8]={-1,1,0,0};
const int dy[8]={0,0,-1,1};
int n,ans,ans1,maxn,sum,maxc,c[1010][1010];
char a[1010][1010];
bool f[1010][1010];

void input()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	{
		char s;
		cin>>s;
		a[i][j]=(s=='.')?0:1;	
	}
}
void bfs(int sx,int sy)
{
	int head=0,tail=1;
	q[1].x=sx,q[1].y=sy;
	while(head<=tail)
	{
		head++;
		int tx=q[head].x,ty=q[head].y;
		for(int i=0;i<4;i++)
		{
			int nx=tx+dx[i],ny=ty+dy[i];
			if(a[nx][ny]&&!f[nx][ny]&&nx>=1&&nx<=n&&ny>=1&&ny<=n)
			{
				tail++;
				q[tail].x=nx,q[tail].y=ny;
				f[nx][ny]=1;
				ans++;
				ans1+=c[nx][ny];
			}
		}
	}
}
void zc()
{
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(a[i][j])
			{
				if(!a[i-1][j]) c[i][j]++;
				if(!a[i+1][j]) c[i][j]++;
				if(!a[i][j-1]) c[i][j]++;
				if(!a[i][j+1]) c[i][j]++;	
			}
}
int main()
{
	fre(perimeter);
	input();
	zc();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(a[i][j]&&!f[i][j])
			{
				ans=1,ans1=c[i][j];
				f[i][j]=1;
				bfs(i,j);
				if(maxn<ans) maxn=ans,maxc=ans1;	
				if(maxn==ans) maxc=min(maxc,ans1);
			}
	printf("%d %d\n",maxn,maxc);
	return 0;
}

经验教训:对于极值能用特判就特判,毕竟搜索慢;当然能用bfs就别用dfs(递归太深,会爆栈)。

以下是一个基于栈的出栈序列检查的C语言代码: ```c #include <stdio.h> #include <stdlib.h> #define MAX_STACK_SIZE 100 int stack[MAX_STACK_SIZE]; int top = -1; void push(int val) { if (top == MAX_STACK_SIZE - 1) { printf("Stack overflow\n"); exit(1); } stack[++top] = val; } int pop() { if (top == -1) { printf("Stack underflow\n"); exit(1); } return stack[top--]; } int main() { int n, i, j; int push_seq[MAX_STACK_SIZE], pop_seq[MAX_STACK_SIZE]; printf("Enter the size of the sequence: "); scanf("%d", &n); printf("Enter the push sequence: "); for (i = 0; i < n; i++) { scanf("%d", &push_seq[i]); } printf("Enter the pop sequence: "); for (i = 0; i < n; i++) { scanf("%d", &pop_seq[i]); } i = 0; j = 0; while (i < n && j < n) { if (push_seq[i] == pop_seq[j]) { i++; j++; } else if (top != -1 && stack[top] == pop_seq[j]) { pop(); j++; } else { push(push_seq[i++]); } } while (top != -1 && j < n) { if (stack[top] == pop_seq[j]) { pop(); j++; } else { break; } } if (top == -1 && j == n) { printf("The pop sequence is valid.\n"); } else { printf("The pop sequence is not valid.\n"); } return 0; } ``` 该程序要求用户输入一个序列的大小,一个压栈序列和一个出栈序列。然后,程序使用一个基于栈的算法来检查出栈序列的合法性。如果出栈序列是合法的,程序将输出“ The pop sequence is valid.”,否则输出“The pop sequence is not valid.”。 该算法的基本思想是模拟压栈和出栈过程。我们从压栈序列的开头开始遍历,遇到一个和出栈序列的当前元素相等的元素时,我们将它出栈。否则,我们将该元素压入栈中。如果栈顶元素和出栈序列的当前元素相等,则将栈顶元素出栈。 在遍历完压栈序列后,我们检查栈中剩余的元素是否可以与出栈序列中的元素匹配。如果可以,则弹出栈顶元素并移动到下一个出栈元素。如果不能匹配,则出栈序列无效。 此算法的时间复杂度为O(n),其中n为序列的大小。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值