UVaLive-2995 Image Is Everything

题目描述:

给一个N*N*N的立方体(可以缺少某几块)的六个视图,依次为前、左、后、右、顶、底视图。“."代表可以看透,其他字母代表颜色。每一小方块各个面颜色相同。问这个物体的最大质量。直到读取的N=0为止。

思路:

首先很容易想到的突破口是,如果在这个某个视图下看到的是".",那么说明这个位置往里的n的为止都没有方块。

还有一个突破口:如果某一个地方没有方块,那么从不同视图看到的这个位置的颜色应该不同。

比如,一个3*3*3的组合体,从正面看,第一行,第三块(也就是顶角这一块)缺少。那么从顶视图看,右下角应该看到的是这个位置下面的那一块的颜色。假设为A。那么从右视图看,应该是看到的这个位置左边的那一块的颜色。假设为B。显然不同。

那么就靠这两个想法,一块一块的去掉,直到剩下的组合体满足要求为止。

为了统一计量标准,建立空间直角坐标系。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;

const int maxn=10+5;

int n;
char view[maxn][maxn][maxn],block[maxn][maxn][maxn];           //view是视图数组,block是实际数组

void getPos(int k,int i,int j,int l,int &x,int &y,int &z){     //得到坐标。实际上是建立了(视图,视图行,视图列)和(x,y,z)之间的关系。
	if (k == 0){                                           //空间直角坐标系如下图所示
		x=l; y=j; z=i;
	}
	if (k == 1){
		x=n-1-j; y=l; z=i;
	}
	if (k == 2){
		x=n-1-l; y=n-1-j; z=i;
	}
	if (k == 3){
		x=j; y=n-1-l; z=i; 
	}
	if (k == 4){
		x=n-1-i; y=j; z=l;
	}
	if (k == 5){
		x=i; y=j; z=n-1-l;
	}
}

int main()
{
	while (scanf("%d",&n),n!=0)
	{
		int i,j,k,l;
		char ch;
		for (i=0;i<n;i++)                        //先把所有的block设为#
		{
			for (j=0;j<n;j++)
			{
				for (l=0;l<n;l++)
				{
					block[i][j][l]='#';
				}
			}
		}
		scanf("%c",&ch);
		for (i=0;i<n;++i)
		{
			for (k=0;k<6;++k)
			{
				for (j=0;j<n;++j)
				{
					scanf("%c",&view[k][i][j]);
				}
				scanf("%c",&ch);
			}
		}
		
		for (k=0;k<6;++k)
		{
			for (i=0;i<n;++i)
			{
				for (j=0;j<n;++j)
				{
					if (view[k][i][j] == '.')          //如果在这个视图下看到了·,说明这一排都没有。
					{
						for (l=0;l<n;++l)          //往里面循环
						{
							int x,y,z;
							getPos(k,i,j,l,x,y,z);      //得到坐标
							block[x][y][z]='.';         //设为空标志
						}
					}
				}
			}
		}
		
		for (;;)
		{
			bool done=true;
			for (k=0;k<6;k++)
			{
				for (i=0;i<n;i++)
				{
					for (j=0;j<n;j++)
					{
						if (view[k][i][j] != '.')      //当不是空的时候
						{
							for (l=0;l<n;l++)      //循环向里
							{
								int x,y,z;
								getPos(k,i,j,l,x,y,z);
								if (block[x][y][z] == '.') continue;      //如果这个位置是空就跳过这层循环
								if (block[x][y][z] == '#')                //如果这个位置还没被动过
								{
									block[x][y][z]=view[k][i][j];     //设为view显示的颜色
									break;                            //退出循环
								}
								if (block[x][y][z] == view[k][i][j]) break; //如果用另一个视图标记的颜色和现在视图颜色一样,说明这一块没问题,退出。

								block[x][y][z]='.';                         
								done=false;                      
							}
						}
					}
				}
			}
			if (done) break;                                            //直到完全没有矛盾了退出。
		}
		
		int ans=0;
		for (i=0;i<n;i++)
			for (j=0;j<n;j++)
				for (l=0;l<n;l++)
				{
					if (block[i][j][l] != '.') ans++;
				}
		printf("Maximum weight: %d gram(s)\n",ans);
		
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值