LeetBook《程序员的算法趣题》Q18---水果酥饼日

《程序员的算法趣题》-(日)增井敏克 , 书中为69 道数学谜题编写了解题程序, 编程语言为:Ruby,JavaScript,C语言。

Q18 水果酥饼日

  日本每月的 22 日是水果酥饼日。因为看日历的时候, 22 日的上方刚好是 15日,也就是“‘22’这个数字上面点缀着草莓”(如果将日语的 15 拆为 1 和 5发音,则与日语“草莓”一词发音相同,而水果酥饼中最为著名的就是草莓酥饼。)
 
  切分酥饼的时候,要求切分后每一块上面的草莓个数都不相同。假设切分出来的 N 块酥饼上要各有“1~N 个(共 N(N + 1)÷2 个草莓)”。但这里要追加一个条件,那就是“一定要使相邻的两块酥饼上的数字之和是平方数”。
  举个例子,假设 N = 4 时采用如 图的切法。这时,虽然 1 + 3 =4 得到的是平方数,但“1 和 4” “2和 3” “2 和 4”的部分都不满足条件。

问题
求可以使切法满足条件的最小的 N(N > 1)。

public class lb12_25_水果酥饼日 {

	public static int printMinN() {

		int N = 2;
		while (true) {

			int[] useList = new int[N - 1];
			for (int i = 2; i < N + 1; i++) {
				useList[i - 2] = i;
			}

			// 枚举4,9...平方数,事先计算平方数(最大值为n 的2 倍)
			int len = (int) (Math.sqrt(N * 2)) + 2;
			int sqrt[] = new int[len];
			for (int i = 0; i < len; i++) {
				sqrt[i] = (i + 1) * (i + 1);
			}

			if (check(1, useList, sqrt)) {
				break;
			}

			N += 1;
		}

		return N;
	}

	static List<Integer> list = new ArrayList<>();

	public static boolean check(int start, int[] useList, int[] sqrt) {

		for (int i = 0; i < useList.length; i++) {

			int number = useList[i];
			if (number == 0) {
				continue;
			}

			if (containsNum(number + start, sqrt)) {

				if (useList[useList.length - 1] == 14) {
					list.add(number);
				}

				useList[i] = 0;

				boolean isZero = true;

				for (int n : useList) {
					if (n != 0) {
						isZero = false;
						break;
					}
				}
				// 最后一个number跟1相加
				if (isZero && containsNum(number + 1, sqrt)) {
					return true;
				}
				if (check(number, useList, sqrt)) {
					return true;
				} else {
					// 还原被修改的useList
					useList[i] = number;
				}
			}
		}
		return false;
	}

	public static boolean containsNum(int number, int[] sqrt) {

		for (int i = 0; i < sqrt.length; i++) {
			if (number == sqrt[i]) {
				return true;
			}
		}
		return false;
	}

	public static void main(String[] args) {
		System.out.println(printMinN());
		System.out.println(list);
	}

}

参考:https://blog.csdn.net/cloudly89/article/details/84846650

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值