算法竞赛入门经典(第2版)习题3-10 盒子 Box UVa1587

本文详细分析了算法竞赛入门经典(第2版)中的习题3-10,即UVa1587 - Box问题。通过对长方体边长的性质探讨,得出长方体边长最多有3种可能,且每种至少包含4个边。文章介绍了特殊情况,如长宽相等时的两种特殊情况,并提出了校验逻辑:边长分类后,根据各类边的数量判断是否可能构成长方体。通过逻辑校验,若满足特定条件,则输出“POSSIBLE”,否则输出“IMPOSSIBLE”。作者在理清逻辑和调试程序上花费了数小时,最终实现了一次性通过(AC)的解决方案。
摘要由CSDN通过智能技术生成

首先考虑长方体的性质,长方体有12条边,可以将其分为3组,每组4条边,这4条边可以认为分属4个矩形,其长度是相等的

依此判断所有12个能够构成长方体矩形的边最多只能有3种长度可能,每种可能至少要包含4个边,且这4个边要来自4个不同矩形

考虑此分类的特殊情况,如果出现长宽相等的矩形,那么只有以下2种特殊情况

1.所有12个边的长度将只能分为2种,一种包含8个边另一种包含4个边

2.所有12个边的长度都相等


校验逻辑

1.所有长宽数据按长度分类

2.每个分类可能包含的长度数量情况为(4,4,4)/(4,8)/(12),如果出现其他情况则输出”IMPOSSIBLE“

3.(4,4,4)情况,如果任意分类内有2条边来自同一个矩形则输出”IMPOSSIBLE“,否则输出”POSSIBLE“

4.(4,8)情况,如果数量为4的分类内有2条边来自同一个矩形则输出”IMPOSSIBLE“,否则输出”POSSIBLE“

5.(12)情况,输出”POSSIBLE“

理清逻辑、调试程序用了3、4个小时,一次AC大笑


//#define LOCAL
//#define TESTING
#include<stdio.h>
#include<string.h>

main()
{
#ifdef LOCAL
	freopen("xt3-10.in","r",stdin);
	int T=1;
#endif

	int l[12];
	while(scanf("%d",&l[0])==1)
	{
		int fenlei[3],amt[3],ind1,ind2,flind[3][12],first[3];
		bool ok = false;		
		memset(fenlei,0,sizeof(fenlei));
		memset(amt,0,sizeof(amt));
		memset(first,1,sizeof(first));
		memset(flind,0,sizeof(flind));
#ifdef TESTING		
		printf("Case %d\n",T);
		T++;
#endif		
		fenlei[0]=l[0];		
		flind[0][amt[0]]=0;
		amt[0]++;
		
//读取数据 
		for(int i = 1; i < 12; i++) 
		{				
			scanf("%d",&l[i]); 
		}		
//读取数据结束

//分类,设置分类开始位置标记,统计分类数量 
		for(int i = 1; i < 12; i++)
		{		
			if(l[i] == fenlei[0])
			{
				flind[0][amt[0]]=i;
				amt[0]++;
			}
			else if(first[0])
			{
				fenlei[1]=l[i];	
				flind[1][amt[1]]=i;
				amt[1]++;
				ind1=i;
				first[0] = 0;
			}
			else if(l[i] == fenlei[1])
			{					
				flind[1][amt[1]]=i;
				amt[1]++;
			}
			
			else if(first[1])
			{
				fenlei[2] = l[i];
				flind[2][amt[2]]=i;
				amt[2]++;
				ind2=i;
				first[1] = 0;
			}
			else if(l[i] == fenlei[2])
			{
				flind[2][amt[2]]=i;
				amt[2]++;
			}
			else break;			
		}
//分类,设置分类开始位置标记,统计分类数量结束

//校验(12)
			if(amt[0]==12)
			{		
				ok = true;
			}
//校验(12)结束

 //校验(4,8)/(8,4)
 			if((amt[0]==4)&&(amt[1]==8))
 			{
	//检查分类0是否来自4个矩形
				bool flag = true;
				for(int i = 1; i < 4; i++)
				{
					int temp1=flind[0][i],temp2=flind[0][i-1];
					if(temp1/2 == temp2/2)
					{					
						flag = false;
						break;
					}
				}
				if(flag) ok = true;
	//检查分类0是否来自4个矩形结束
 			}
 			else if((amt[0]==8)&&(amt[1]==4))
 			{
	//检查分类1是否来自4个矩形
 				bool flag = true;
 				for(int i = 1; i < 4; i++)
				{
					int temp1=flind[1][i],temp2=flind[1][i-1];
					if(temp1/2 == temp2/2)
					{					
						flag = false;
					}
				}
				if(flag) ok = true;
	//检查分类1是否来自4个矩形
 			}
//校验(4,8)/(8,4) 结束
 
//校验(4,4,4)
		if((amt[0]==4)&&(amt[1]==4)&&(amt[2]==4))
		{
	//检查分类0/1/2是否来自4个矩形
			bool flag = true;		
			for(int i = 1; i < 4; i++)
			{
				int temp1=flind[0][i],temp2=flind[0][i-1];
				int temp3=flind[1][i],temp4=flind[1][i-1];
				int temp5=flind[2][i],temp6=flind[2][i-1];
				if((temp1/2 == temp2/2)||(temp3/2 == temp4/2)||(temp5/2 == temp6/2))
				{					
					flag = false;
				}
			}
			if(flag) ok = true;
	//检查分类0/1/2是否来自4个矩形结束
		}
//校验(4,4,4) 结束		

		
		if(ok) printf("POSSIBLE\n");
		else printf("IMPOSSIBLE\n");		
#ifdef TESTING		
		for(int i = 0; i < 6; i++) printf("i=%d %d %d \n", i, l[2*i], l[2*i+1]);
		for(int i = 0; i < 3; i++) printf("i=%d fenlei=%d amt=%d \n", i, fenlei[i], amt[i]);
		for(int i = 0; i < 3; i++)
		{
			for(int j = 0; j < 8; j++) printf("flind[%d][%d]=%d /", i, j, flind[i][j]);
			printf("\n");			
		} 
		 
		printf("\n"); 
#endif	

	}
	return 0;
}





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值