题目描述
凑平方数
把0~9这10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。
比如:0, 36, 5948721
再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
等等...
大家注意正确的答案是300,这是官方给的答案。
思路
这道题思路很简单就是数据量大了,主要题意就是说让你把一个数字串分割,然后每个小分组都是平方数。
这道题可以从结果来推,先把10位以内所有平方数算出来当然要用到大整数不然会溢出。然后对这600多个数进行全排列,在排列过程中当然还要减支。
减支1:几个分组合在一起的字符串不能超过10个
减支2:剩下可用长度比当前选择的字符串长度还小后面就不用看了,因为我们生成平方数从小到大生成的,后面的数肯定比当前的大(这个减支不必须只是会大大降低时间),比当前数大也就意味着基本比当前数长很多。毕竟是平方肯定不会存在下个平方数比当前平方数还短的情况。
减支3:当前选的数不能和前面已经选的字符串有相同字符,这个题目有要求。
正确答案是:300
具体代码:
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
public class SelPow {
//保存10位以内所有的平方数,方便进行全排列
static ArrayList<BigInteger> digitlist;
//在深度优先搜索过程中标记digitlist中数字是否被选
public static boolean[] select;
// 检查当前字符串是否有相同字符
public static boolean check(String digitstr) {
int len = digitstr.length();
Set<Character> set = new HashSet<>();
for (int i = 0; i < len; i++)
set.add(digitstr.charAt(i));
if (set.size() == len)
return true;
else
return false;
}
// 保存所有的结果用集合去重,题目要求说生成的序列是无序的
public static Set<Set<String>> result = new HashSet<>();
//对所有的平方数排列
//dfs(还剩多少待选数字,之前选好的合并的数字串(方便检查是否有重复数字), 之前选好的数字集合)
public static void dfs(int len, String figure, Set<String> figureset) {
if (len < 0)
return;
if (len == 0) {
result.add(figureset);//满足条件加入到结果集合中
return;
}
// 填剩下的那len个数字,当然不只填一个数可以很多,但一次dfs只填一个剩下的交给下一次dfs
for (int i = 0; i < select.length; i++) {
if (!select[i]) {
select[i] = true;
String temp = digitlist.get(i).toString();
//因为最先所有的平方数最先都是从小到大生成的后面的数肯定比当前的数要长因此后面就不用看了
if (len < temp.length()) {
select[i] = false;
break;
}
//检查当前选的数字是否和以前选的有重复数字如果有则放弃这个,否则进行下一层dfs
if (check(figure + temp)) {
HashSet<String> tempset = new HashSet<>();
tempset.addAll(figureset);
tempset.add(temp);
dfs(len - temp.length(), figure + temp, tempset);
}
select[i] = false;
}
}
}
public static void main(String[] args) {
int i = 0;
digitlist = new ArrayList<>();
//由小到大生成平方数
while (true) {
BigInteger temp = BigInteger.valueOf(i++).pow(2);
if (temp.toString().length() <= 10) {
if (check(temp.toString()))
digitlist.add(temp);
} else
break;
}
select = new boolean[digitlist.size()];
dfs(10, "", new HashSet<String>());
// 输出最终计算出的所有结果数目
System.out.println(result.size());
}
}