求金属融化所需要的时间
1) 在N × N的格子上放置着形状不规则的金属(5≤N≤1000)。
- 金属为1×1格子的整数倍组成的不规则形状;
- 金属有可能中空,这样在开始的时刻中空的方格不会立即充满液体;
- 当中空的格子有缺口时,液体可以立即进入到中空的地方。
2) T=0时刻从格子的最外围开始注入某种可以融化金属的液体。
- 液体扩散填充的速度不计,例如在T=0时刻液体充满浅蓝色方块。
3) 当金属块上、下、左、右4个方向中至少有两个方向邻接液体的时候,金属块融化,耗时1个时间单位。
- 例如图中标记为1的点为T=1时刻将要融化的点;
- 当金属中空的部分暴露出来时,例如图中的T=2时刻液体会立刻充满可连接的中空部分,液体扩散的时间不计。如图中在T=5的时刻金属融化。
例 输入:N=16
________________
________________
__##____________
__########______
___####__#####__
___#_##___####__
___#_####_##____
_____########___
_______###______
________________
____#######_____
_____######_____
______##__##____
_______#####____
________________
________________
输出:5
提示:
1 输入的图对应的直观效果如下所示。
2 液体与中空的符号是相同的,需要加以区别。
3 可以借助于图的遍历算法实现。
代码(vs2012):
#include<iostream>
using namespace std;
static int N, T;
char **a;
void input();
void adjust1();
void adjust2();
void melt();
void output();
void main()
{
input();
adjust1();
output();
melt();
}
void input()
{
cout << "please input N:" << endl;
cin >> N;
a = new char*[N];
for (int i = 0; i < N; i++)
a[i] = new char[N];
cout << "input the design:" << endl;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
cin >> a[i][j];
}
void output()
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
cout << a[i][j];
cout << endl;
}
cout << endl;
}
void adjust1()
{
for (int m = 0; m < N; m++)
for (int n = 0; n < N; n++)
{
if (a[m][n] == '_'&&m>0 && n>0 && m<N - 1 && n<N - 1)
{
int x = 0;
int I1 = m, I2 = m, J1 = n, J2 = n;
while (I1 > -1)
{
if (a[I1--][n] == '#')
{
x++;
break;
}
}
while (I2 <N)
{
if (a[I2++][n] == '#')
{
x++;
break;
}
}
while (J1>-1)
{
if (a[m][J1--] == '#')
{
x++;
break;
}
}
while (J2<N)
{
if (a[m][J2++] == '#')
{
x++;
break;
}
}
if (x == 4)
a[m][n] = '*';
}
}
}
void adjust2()
{
for (int m = 0; m < N; m++)
for (int n = 0; n < N; n++)
{
if (a[m][n] == '*'&&m>0 && n>0 && m<N - 1 && n<N - 1)
{
int x = 0;
int I1 = m, I2 = m, J1 = n, J2 = n;
while (I1 > -1)
{
if (a[I1--][n] == '#')
{
x++;
break;
}
}
while (I2 <N)
{
if (a[I2++][n] == '#')
{
x++;
break;
}
}
while (J1>-1)
{
if (a[m][J1--] == '#')
{
x++;
break;
}
}
while (J2<N)
{
if (a[m][J2++] == '#')
{
x++;
break;
}
}
if (x < 4)
a[m][n] = '!';
}
}
while (1)
{
int l = 0;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
{
if (a[i][j] == '!')
{
if (i>0 && a[i - 1][j] == '*')
{
l++;
a[i - 1][j] = '!';
}
if (i < N - 1 && a[i + 1][j] == '*')
{
l++;
a[i + 1][j] = '!';
}
if (j>0 && a[i][j - 1] == '*')
{
l++;
a[i][j - 1] = '!';
}
if (j < N - 1 && a[i][j + 1] == '*')
{
l++;
a[i][j + 1] = '!';
}
}
}
if (l == 0)
break;
}
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
if (a[i][j] == '!')
a[i][j] = '_';
}
void melt()
{
T = 0;
while (1)
{
int y = 0;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
if (a[i][j] != '_')
y++;
if (y == 0)
break;
for (int m = 0; m < N; m++)
for (int n = 0; n < N; n++)
{
if (a[m][n] == '#')
{
int x = 0;
if (m>0 && a[m - 1][n] == '_')
x++;
if (m<N - 1 && a[m + 1][n] == '_')
x++;
if (n>0 && a[m][n - 1] == '_')
x++;
if (n<N - 1 && a[m][n + 1] == '_')
x++;
if (x>1)
a[m][n] = '0';
}
}
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
{
if (a[i][j] == '0')
a[i][j] = '_';
}
T++;
cout << "下一步" << endl;
adjust2();
output();
}
cout << T;
system("pause");
}