题目链接:点击这里
结题思路
此题实在是不会。。。后面看书看了好久才慢慢明白,赶紧拿小本本记下来。
思路是这样的:
首先,如果有能穿透的位置,则当前位置所对应的所有单位立方体都不存在。
如果同一个位置的单位立方体,从不同视图上看颜色不一样,则这个单位立方体不存在。
书上用数学归纳法证明了可以通过同个位置不同视图的颜色不一致来找到最多能删除的个数。
因此,结题的关键首先是要将6个视图与三维中的实际位置对应起来,这个应该不难,但首先要确定坐标轴。
然后在通过之前说的数学归纳法去逐个检查每个位置的单位立方体是否存在,若无法删除更多的单位立方体,则为答案。
注意事项
此题书上的代码使用了宏来精简程序,使用还不够熟练。
对于get函数
中的len
变量,必须要按照当前视图的从近到远
进行循环。
AC代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
#define REP(i,n) for (int i = 0; i < (n);i++)
const int maxn = 10;
int n;
char pos[maxn][maxn][maxn];
char view[6][maxn][maxn];
char read_color()
{
char temp;
while (1)
{
cin>>temp;
if ((temp >= 'A' && temp <= 'Z') || temp == '.')
return temp;
}
}
void get(int k,int i,int j,int len,int &x,int &y,int &z)
{
if (k == 0)
//前视图
{
x = j;
y = len;
z = i;
}
else if (k == 1)
//左视图
{
x = len;
y = n - 1 - j;
z= i;
}
else if (k == 2)
//后视图
{
x = n - 1 - j;
y = n - 1 - len; //从最后一个单位立方体开始看
z = i;
}
else if (k == 3)
//右视图
{
x = n - 1 - len;
y = j;
z = i;
}
else if (k == 4)
//顶视图
{
x = j;
y = n - 1 - i;
z = len;
}
else
//底视图
{
x = j;
y = i;
z = n - 1 - len;
}
}
int main()
{
while (cin>>n && n)
{
REP(i,n) REP(k,6) REP(j,n)
view[k][i][j] = read_color(); //i 表示第几行,j表示一行中的第几个, k表示6个视图
REP(i,n) REP(j,n) REP(k,n)
pos[i][j][k] = '#'; //初始化
REP(k,6) REP(i,n) REP(j,n)
if (view[k][i][j] == '.') //若可透视,则一排的单位立方体都不存在,因此一个循环解决
REP(p,n)
{
int x,y,z;
get(k,i,j,p,x,y,z);
pos[x][y][z] = '.';
}
while(1)
{
bool done = true;
REP(k,6) REP(i,n) REP(j,n)
if (view[k][i][j] != '.') //若不可透视
REP(p,n)
{
int x,y,z;
get(k,i,j,p,x,y,z);
if (pos[x][y][z] == '.') continue;
if (pos[x][y][z] == '#')
{
//若还没有颜色,则赋予颜色
pos[x][y][z] = view[k][i][j];
break;
}
//若已经有颜色,且与这个视角中的颜色相同
if (pos[x][y][z] == view[k][i][j])
break;
//若颜色不相同,则删除
pos[x][y][z] = '.';
done = false;
}
if (done) break;
}
int ans = 0;
REP(i,n) REP(j,n) REP(k,n)
if (pos[i][j][k] != '.')
ans++;
cout<<"Maximum weight: "<<ans<<" gram(s)"<<endl;
}
return 0;
}
最后,欢迎关注我的个人博客~