火柴棍是这么玩的

       不正经模式:

        父亲今天买了包火柴点烟(鬼知道他为什么不用打火机),闲来无事的我把父亲没有用的火柴取出来放在桌子上,开始摆弄起来。由于尺寸大了一点,1这个数字用两根竖着的火柴棒表示。(注意,这句话很重要)

举个例子:

        

        额貌似不怎么形象,就这样好了。你只知道我因为摆弄火柴的时候《突发奇想》就出了一个题就行了。

        正经模式:

        废话不多说,你看见标题的时候是不是认为我在玩小孩子家家的儿戏?NONONO,小伙子你格局小了,既然我都说了火柴棍可以“这么玩”,那肯定就有它的独特之处。

        这不是儿戏,而是我将要出的一道题,编程语言是C++。

        现在假设桌子上有14根火柴棍,则可以拼出两种不同的等式:0+1=1和1+0=1,数字可能有些抽象,我画了个图示意一下:

        0+1=1和1+0=1本质没有什么区别,我就不画0+1=1了。由图可知,火柴棍总数为2+2+6+2+2=14。

        我直接说吧,在我的规定里,0由6根棍子组成,1由2根棍子组成,2由5根棍子组成,3由5根棍子组成,4由4根棍子组成,5由5根棍子组成,6由6根棍子组成,7由3根棍子组成,8由7根棍子组成,9由6根棍子组成。

        另:内容也许很枯燥,但是坚持突破很酷!

发现规律了吗?只要拼的出来等式,它就一定会有2个及以上的组合。而最少的两个,其实就是加法交换律。

题目描述:

假如现在我手上有n根(n<=24)火柴棍,那么我能拼出多少个不同?+?=?的等式呢?

注意:

1.加号和等号各自需要两根火柴棍。

2.如果A≠B,则A+B=C与B+A=C视为不同的等式(A,B,C都大于0)

3.所有火柴棍必须全部用上。

输入格式:

一个整数n,表示火柴棍的总数。

输出格式:

符合条件的等式,每行一组。(顺序由第一个数从小到大)

样例输入:

18

样例输出:

0+4=4

0+11=11

1+10=11

2+2=4

2+7=9

4+0=4

7+2=9

10+1=11

11+0=11

分析:

        呵呵,我相信很多人看完题目后都是灵光乍现,脑袋里闪出两个字:枚举!

        是的,这玩意儿最好做的就是枚举,但这并不意味着没有其他方法。

        既然是要找到形如A+B=C这样的等式,那最简单的方法就是分别枚举A,B,C。

        好现在问题来了:怎么找范围?

        呵呵,我们只需要在0~1111之间枚举就可以了。你问我为什么?因为我给的题目中火柴棍最多只有24根,除去+号和=号最多只有20根,而0~9的数字之中,1用到的火柴棍最少,只需要2根,而20个火柴棍刚好能组成10个1,那也就是说,ABC三个数所需的根数都<=1111。

        这里只需要枚举A,B就可以了,C可以通过A,B算出来,这样减少了时间复杂度,有的时候做题也是这样啊,要去实行剪枝、优化程序。我的思路是将0~9所需的火柴数分别用一个a[]数组存起来。

        OK,直接给代码,我与标注释,应该看得懂吧(汗):

#include<bits/stdc++.h>
using namespace std;
int f(int x)
{
	int num=0;//用来记录初始化,一定要记得初始化。
	int a[10]={6,2,5,5,4,5,6,3,7,6}; 
	//用一个a[]数组存0~9分别需要的火柴棍数量。
	while(x/10!=0)//如果这个数除以10不等于0的话,那就证明它至少有两位。
	{
		//获得x的末尾数字并将此数所需要用到的火柴棍棍数累加到num中。 
		num+=a[x%10];
		x/=10;//去掉x末尾的数字,这里的操作就是在遍历一个数的各位。 
	} 
	num+=a[x];
	return num;
}	
int main()
{
	int a,b,c,n,sum=0;
	cin>>n;
	for(int a=0;a<=1111;a++)
	{
		for(int b=0;b<=1111;b++)
		{
			c=a+b;
			if(f(a)+f(b)+f(c)==n-4)//n-4就是减去+号和=号所用的火柴棍。
			{
				cout<<a<<'+'<<b<<'='<<c<<endl;
			} 
		}
	}
	return 0;
}

哈哈,自豪一下,减少时间复杂度是我自己想出来的呢。

不要小看!原本是O(N^3)优化到了O(N^2)呢!

还是那句话,写程序要多动脑子,多想,不然会没有突破。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值