查找并输出给定数字的最短平方和。
示例:12 = 2^2 + 2^2 + 2^2 (not 3^2 + 1^2 + 1^2 + 1^2)
输出:{2 2 2}
答案 0 :(得分:7)
这是最小币变化问题,其中硬币为[1,4,9,...,(ceil(sqrt(n)))^2]
。
可以使用Dynamic Programming (DP)按照递归公式解决:
D(i,0) = 0
D(i,x) = infinity x<0
D(0,x) = infinity x>0
D(i,x) = min { D(i,x-i^2) + 1, D(i-1,x) }
在构建矩阵时(假设自下而上的DP),D(ceil(sqrt(n)),n)
中矩阵中表示的元素是构建输入数字所需的最小数量的“硬币”(平方数)。
获取实际元素是通过在构建矩阵后跟踪您在矩阵中的选择来完成的,并在每个点检查您是否添加了一个加数。
更详细地解释了this thread和this thread中的类似问题。
答案 1 :(得分:0)
这是问题的视觉基本解决方案。 需要进行编辑以缓存中间答案,以便算法明显更快。目前......只能快速计算出大约40到50的值。这是完全工作和测试。它只返回最短的答案,而其中一个值高于其他值的左侧。
Private Function ShortestSquareSum(x As Integer) As Integer()()
If x < 0 Then
Throw New ArgumentException("Parameter cannot be negative.", "x")
ElseIf x = 0 Then
Return New Integer()() {New Integer() {}}
Else
Dim answers As New List(Of Integer())
Dim shortest As Integer? = Nothing
For y As Integer = Math.Floor(Math.Sqrt(x)) To 1 Step -1
Dim remaining As Integer = x - y * y
Dim tempAnswers As Integer()() = ShortestSquareSum(x - y * y)
For Each answer As Integer() In tempAnswers
Dim currentAnswer As New List(Of Integer)
currentAnswer.Add(y)
currentAnswer.AddRange(answer)
If Not shortest.HasValue OrElse currentAnswer.Count < shortest Then
shortest = currentAnswer.Count
answers.Clear()
answers.Add(currentAnswer.ToArray())
ElseIf currentAnswer.Count = shortest AndAlso (answer.Count = 0 OrElse y > answer(0)) Then
answers.Add(currentAnswer.ToArray())
End If
Next
Next
Return answers.ToArray()
End If
End Function
答案 2 :(得分:0)
public static void shortest_square(int n)
{
int i=2;
List<Integer> list= new ArrayList<Integer>();
while(i<=n) || n!=0)
{
if(n%(i*i)==0)
{
n=n-(i*i);
list.add(i);
}
else
{
i++;
}
}
System.out.println(list);
}