如何确定一组数字是否可以组成某个数字?
How can I determine if a certain number can be made up from a set of numbers?
所以我有一个整数,例如1234567890,以及一组给定的数字,例如{4、7、18、32、57、68}
问题是1234567890是否可以由给定的数字组成(你可以多次使用一个数字,也不必全部使用)。在上述情况下,一种解决方案是:
38580246 * 32 + 1 * 18
(不需要给出具体的解决方案,只要能做到)
我的想法是尝试所有解决方案。例如我会尝试
1 * 4 * + 0 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 4
2 * 4 * + 0 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 8
3 * 4 * + 0 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 12
.....
308 641 972 * 4 * + 0 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 1234567888
308 641 973 * 4 * + 0 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 1234567892 ==> 超过
0 * 4 * + 1 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 7
1 * 4 * + 1 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 11
2 * 4 * + 1 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 15
等等...
这是我在 C# 中的代码:
static int toCreate = 1234567890;
static int[] numbers = new int[6] { 4, 7, 18, 32, 57, 68};
static int[] multiplier;
static bool createable = false;
static void Main(string[] args)
{
multiplier = new int[numbers.Length];
for (int i = 0; i < multiplier.Length; i++)
multiplier[i] = 0;
if (Solve())
{
Console.WriteLine(1);
}
else
{
Console.WriteLine(0);
}
}
static bool Solve()
{
int lastIndex = 0;
while (true)
{
int comp = compare(multiplier);
if (comp == 0)
{
return true;
}
else if (comp < 0)
{
lastIndex = 0;
multiplier[multiplier.Length - 1]++;
}
else
{
lastIndex++;
for (int i = 0; i < lastIndex; i++)
{
multiplier[multiplier.Length - 1 - i] = 0;
}
if (lastIndex >= multiplier.Length)
{
return false;
}
multiplier[multiplier.Length - 1 - lastIndex]++;
}
}
}
static int compare(int[] multi)
{
int osszeg = 0;
for (int i = 0; i < multi.Length; i++)
{
osszeg += multi[i] * numbers[i];
}
if (osszeg == toCreate)
{
return 0;
}
else if (osszeg < toCreate)
{
return -1;
}
else
{
return 1;
}
}
代码工作正常(据我所知)但是太慢了。解出这个例子大约需要3秒,100个数字可能有10000个数字。
没有办法测试该解决方案,但以下应该可以。
给定一个目标数字 target
和一组 numbers
有效数字:
bool FindDecomposition(int target, IEnumerable<int> numbers, Queue<int> decomposition)
{
foreach (var i in numbers)
{
var remainder = target % i;
if (remainder == 0)
{
decomposition.Enqueue(i);
return true;
}
if (FindDecomposition(remainder, numbers.Where(n => n < i), decomposition))
{
return true;
}
}
return false
}
从 decomposition
构建 n
非常简单。
您总是可以尝试结合使用取模函数和 LINQ 表达式来解决问题。
您将有一个列表和一个 运行 模变量来跟踪您在迭代中所处的位置。那就简单的用递归判断你是否满足条件吧
一个例子如下:
static int toCreate = 1234567890;
static List<int> numbers = new List<int> { 4, 7 };
static void Main(string[] args)
{
numbers.Sort();
numbers.Reverse();
Console.WriteLine(Solve(numbers,toCreate).ToString());
}
static bool Solve(List<int> lst1, int runningModulo)
{
if (lst1.Count == 0 && runningModulo != 0)
return false;
if (lst1.Count == 0 || runningModulo == 0)
return true;
return numbers.Any(o => o < (toCreate % lst1.First())) ? //Are there any in the remaining list that are smaller in value than the runningModulo mod the first element in the list.
Solve(lst1.Where(o => o != lst1.First()).ToList(), runningModulo % lst1.First()) //If yes, then remove the first element and set the running modulo = to your new modulo
: Solve(lst1.Where(o => o != lst1.First()).ToList(), toCreate); //Otherwise, set the running modulo back to the original toCreate value.
}
我有一个递归的解决方案。它在大约 0.005 秒内(在我的机器上)解决了 OP 的原始问题,并告诉您计算结果。
private static readonly int Target = 1234567890;
private static readonly List<int> Parts = new List<int> { 4, 7, 18, 32, 57, 68 };
static void Main(string[] args)
{
Console.WriteLine(Solve(Target, Parts));
Console.ReadLine();
}
private static bool Solve(int target, List<int> parts)
{
parts.RemoveAll(x => x > target || x <= 0);
if (parts.Count == 0) return false;
var divisor = parts.First();
var quotient = target / divisor;
var modulus = target % divisor;
if (modulus == 0)
{
Console.WriteLine("{0} X {1}", quotient, divisor);
return true;
}
if (quotient == 0 || parts.Count == 1) return false;
while (!Solve(target - divisor * quotient, parts.Skip(1).ToList()))
{
if (--quotient != 0) continue;
return Solve(target, parts.Skip(1).ToList());
}
Console.WriteLine("{0} X {1}", quotient, divisor);
return true;
}
基本上,它会遍历每个数字,看看在给定当前商和数字的情况下是否存在可能的解决方案 "below"。如果没有,它从商中减去 1 并重试。它会一直这样做,直到用尽该数字的所有选项,然后继续移动到下一个数字(如果可用)。如果所有的数字都用完了,就没有解了。
所以我有一个整数,例如1234567890,以及一组给定的数字,例如{4、7、18、32、57、68}
问题是1234567890是否可以由给定的数字组成(你可以多次使用一个数字,也不必全部使用)。在上述情况下,一种解决方案是:
38580246 * 32 + 1 * 18
(不需要给出具体的解决方案,只要能做到)
我的想法是尝试所有解决方案。例如我会尝试
1 * 4 * + 0 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 4
2 * 4 * + 0 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 8
3 * 4 * + 0 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 12
.....
308 641 972 * 4 * + 0 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 1234567888
308 641 973 * 4 * + 0 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 1234567892 ==> 超过
0 * 4 * + 1 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 7
1 * 4 * + 1 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 11
2 * 4 * + 1 * 7 + 0 * 18 + 0 * 32 + 0 * 57 + 0 * 68 = 15
等等...
这是我在 C# 中的代码:
static int toCreate = 1234567890;
static int[] numbers = new int[6] { 4, 7, 18, 32, 57, 68};
static int[] multiplier;
static bool createable = false;
static void Main(string[] args)
{
multiplier = new int[numbers.Length];
for (int i = 0; i < multiplier.Length; i++)
multiplier[i] = 0;
if (Solve())
{
Console.WriteLine(1);
}
else
{
Console.WriteLine(0);
}
}
static bool Solve()
{
int lastIndex = 0;
while (true)
{
int comp = compare(multiplier);
if (comp == 0)
{
return true;
}
else if (comp < 0)
{
lastIndex = 0;
multiplier[multiplier.Length - 1]++;
}
else
{
lastIndex++;
for (int i = 0; i < lastIndex; i++)
{
multiplier[multiplier.Length - 1 - i] = 0;
}
if (lastIndex >= multiplier.Length)
{
return false;
}
multiplier[multiplier.Length - 1 - lastIndex]++;
}
}
}
static int compare(int[] multi)
{
int osszeg = 0;
for (int i = 0; i < multi.Length; i++)
{
osszeg += multi[i] * numbers[i];
}
if (osszeg == toCreate)
{
return 0;
}
else if (osszeg < toCreate)
{
return -1;
}
else
{
return 1;
}
}
代码工作正常(据我所知)但是太慢了。解出这个例子大约需要3秒,100个数字可能有10000个数字。
没有办法测试该解决方案,但以下应该可以。
给定一个目标数字 target
和一组 numbers
有效数字:
bool FindDecomposition(int target, IEnumerable<int> numbers, Queue<int> decomposition)
{
foreach (var i in numbers)
{
var remainder = target % i;
if (remainder == 0)
{
decomposition.Enqueue(i);
return true;
}
if (FindDecomposition(remainder, numbers.Where(n => n < i), decomposition))
{
return true;
}
}
return false
}
从 decomposition
构建 n
非常简单。
您总是可以尝试结合使用取模函数和 LINQ 表达式来解决问题。
您将有一个列表和一个 运行 模变量来跟踪您在迭代中所处的位置。那就简单的用递归判断你是否满足条件吧
一个例子如下:
static int toCreate = 1234567890;
static List<int> numbers = new List<int> { 4, 7 };
static void Main(string[] args)
{
numbers.Sort();
numbers.Reverse();
Console.WriteLine(Solve(numbers,toCreate).ToString());
}
static bool Solve(List<int> lst1, int runningModulo)
{
if (lst1.Count == 0 && runningModulo != 0)
return false;
if (lst1.Count == 0 || runningModulo == 0)
return true;
return numbers.Any(o => o < (toCreate % lst1.First())) ? //Are there any in the remaining list that are smaller in value than the runningModulo mod the first element in the list.
Solve(lst1.Where(o => o != lst1.First()).ToList(), runningModulo % lst1.First()) //If yes, then remove the first element and set the running modulo = to your new modulo
: Solve(lst1.Where(o => o != lst1.First()).ToList(), toCreate); //Otherwise, set the running modulo back to the original toCreate value.
}
我有一个递归的解决方案。它在大约 0.005 秒内(在我的机器上)解决了 OP 的原始问题,并告诉您计算结果。
private static readonly int Target = 1234567890;
private static readonly List<int> Parts = new List<int> { 4, 7, 18, 32, 57, 68 };
static void Main(string[] args)
{
Console.WriteLine(Solve(Target, Parts));
Console.ReadLine();
}
private static bool Solve(int target, List<int> parts)
{
parts.RemoveAll(x => x > target || x <= 0);
if (parts.Count == 0) return false;
var divisor = parts.First();
var quotient = target / divisor;
var modulus = target % divisor;
if (modulus == 0)
{
Console.WriteLine("{0} X {1}", quotient, divisor);
return true;
}
if (quotient == 0 || parts.Count == 1) return false;
while (!Solve(target - divisor * quotient, parts.Skip(1).ToList()))
{
if (--quotient != 0) continue;
return Solve(target, parts.Skip(1).ToList());
}
Console.WriteLine("{0} X {1}", quotient, divisor);
return true;
}
基本上,它会遍历每个数字,看看在给定当前商和数字的情况下是否存在可能的解决方案 "below"。如果没有,它从商中减去 1 并重试。它会一直这样做,直到用尽该数字的所有选项,然后继续移动到下一个数字(如果可用)。如果所有的数字都用完了,就没有解了。