在我们的项目中,我们将尝试为不同的图形使用不同的颜色。这些颜色应满足以下条件:
- 所有颜色应满足:abs(AR - AG) + abs(AG - AB) + abs(AB - AR) > 250
- 所有颜色都应该足够不同。如果颜色 A 和 B 相遇:abs(AR - BR) + abs(AG - BG) + abs(AB - BB) >= 50,那么它们就足够不同了。问题是我们最多可以获得多少种颜色?有没有什么快速的方法可以在不枚举所有组合的情况下获得颜色?
这取决于您需要颜色的位置(网站、图片等)。我曾经遇到过一个非常相似的问题,下面是我发现的。最后,我只使用了 HSV 颜色空间(这在我的应用程序中很简单),它允许您将色调范围划分为大小相等的间隔并每次获得不同的颜色。
这是我发现有用的:
我认为获得准确结果的最简单方法是通过拉斯维加斯算法,在该算法中,您尝试通过逐步添加不会使当前集无效的随机颜色来组合尽可能大的颜色集。如果没有这样的颜色可用(例如,因为最后 100 次尝试找到这样的颜色失败),则当前集形成结果。
请注意,当它卡住时,它不会尝试“撤消”可能的错误添加,它只是终止,这使得算法报告许多次优集,但速度非常快。因此,您将需要多次(数千次?)运行此算法,以查看您可以组合多大的集合。
我认为这是以相对较少的编程或分析工作获得体面结果的更快方法之一。
编辑:做了几次快速运行:我发现的由非冲突颜色组成的最大设置大小是273。
编辑 2根据要求,相应的(相关)源代码:
public class Colour
{
public int Red;
public int Green;
public int Blue;
public int Primality
{
get { return Math.Abs(Red - Green) + Math.Abs(Green - Blue) + Math.Abs(Blue - Red); }
}
public int Difference(Colour other)
{
return Math.Abs(this.Red - other.Red) + Math.Abs(this.Green - other.Green) + Math.Abs(this.Blue - other.Blue);
}
public Colour(int red, int green, int blue)
{
Red = red;
Green = green;
Blue = blue;
}
public static Colour Generate(Random rnd)
{
return new Colour(rnd.Next(256), rnd.Next(256), rnd.Next(256));
}
public static Colour GeneratePrimal(Random rnd)
{
Colour candidate = null;
do
{
candidate = Generate(rnd);
} while (candidate.Primality <= 250);
return candidate;
}
}
使用此类,所描述的算法的单次运行将如下所示:
private Random _rnd = new Random();
public List<Colour> Run()
{
List<Colour> resultSet = new List<Colour>();
//Shouldn't find a set larger than 1000 Colours.
for (int colourCount = 0; colourCount < 1000; colourCount++)
{
Colour candidate = null;
bool found = false;
//100000 means: Try *very* hard to find a next candidate
for (int index = 0; index < 100000; index++)
{
candidate = Colour.GeneratePrimal(_rnd);
if (resultSet.Any(col => candidate.Difference(col) < 50) == false)
{
resultSet.Add(candidate);
found = true;
break;
}
}
if (found == false)
return resultSet;
}
return resultSet;
}