示例
输入:
stepSize = 0.5和numDimensions = 3(即3D空间)
输出:
0.0, 0.0, 1.0
0.0, 0.5, 0.5
0.0, 1.0, 0.0
0.5, 0.0, 0.5
0.5, 0.5, 0.0
1.0, 0.0, 0.0
由于我们需要找到所有可能的点,我想到了递归解决方案。这是我的代码:
class PointEnumeration {
static class Point {
List<Float> dimensions; //a list of float where index i is the (i+1)'th dimension
Point(Point p) {
this.dimensions = new ArrayList<>();
this.dimensions.addAll(p.dimensions);
}
Point(int size) {
this.dimensions = new ArrayList<>();
for(int i = 0; i < size; i++){
//Initialize all dimensions to 0.0f
this.dimensions.add(0.0f);
}
}
void incr(int pos, float i) {
float val = dimensions.get(pos);
dimensions.set(pos, val + i);
}
void set(int pos, float i) {
dimensions.set(pos, i);
}
float get(int pos){
return dimensions.get(pos);
}
}
static List<Point> findPoints(float stepSize, int numDim) {
if (stepSize > 1) {
return new ArrayList<>();
}
List<Point> res = new ArrayList<>();
for(float i = stepSize; i <= 1; i+=stepSize) {
findPointsHelper(i, numDim, 1.0f, 0, new Point(numDim), res);
}
return res;
}
static void findPointsHelper(float stepSize, int numDim, float sum, int start, Point curr, List<Point> res) {
if (sum == 0.0) {
res.add(new Point(curr));
return;
}
for (int i = start; i < numDim; i++) {
float temp = sum;
float val = curr.get(i);
curr.incr(i, stepSize);
findPointsHelper(stepSize, numDim, sum - stepSize, i + 1, curr, res);
curr.set(i, val);
sum = temp;
}
}
public static void main(String[] args) {
List<Point> res = findPoints(0.25f, 4); //Tried 1.0f, 3 and 0.5f, 3 as well
for (Point p : res) {
for (Float coord : p.dimensions) {
System.out.print(String.valueOf(coord) + ", ");
}
System.out.println(" ");
}
}
}
这似乎适用于我尝试过的一些测试用例。 (stepSize = 0.5f和numDimensions = 3)的示例输出:
0.5, 0.5, 0.0,
0.5, 0.0, 0.5,
0.0, 0.5, 0.5,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
我有几个问题:
修改 我错过了第三个约束:维度的所有值的总和必须总和为1.0(道歉,我之前忘记提及)。
答案 0 :(得分:3)
每个维度和V = ValuesCount = 1 + 1/stepSize
维度都有nD
个可能的值。
1D中有V点,2D中有V * V点,3D中有V ^ 3,nD维空间中有V^nD
个点。
请注意,您可以在简单的for-cycle
中生成所有点坐标 for k = 0..V^nD - 1
represent k in V-ary number system
m-th digit of k is coordinate of the k-th point in m-th dimension
(divide by (V-1) to normalize to range 0..1)
你的V = 3,nD = 3案例的例子:
k = 15(dec) = 120(trinary)
first (right) digit is 0, second is 2, third is 1
coordinates (0.0, 1.0, 0.5)
答案 1 :(得分:2)
- 我解决这个问题的方法是否正确?
醇>
我没有查看您的代码,但您的示例输出缺少几点。应该有27个。
请注意,由于循环变量中累积的错误,使用带浮点数的for循环可能会导致问题。最好循环整数,然后在循环内部划分:
for (int i = 0; i <= 9; ++i) {
System.out.println(i / 9.0);
}
而不是
for (double i = 0; i <= 1; i += 1.0 / 9.0) {
System.out.println(i);
}
(Compare the output of the two - 注意第二种情况下的不准确以及少打印一行)
- 是否有更有效的算法来解决这个特殊问题?
醇>
每个坐标都有1 + 1/stepSize
个值;有numDimensions
个坐标。因此,该空间应该有(1 + 1/stepSize)^numDimensions
个不同的点。
因此,迭代所有点的最佳复杂度是O((1 + 1/stepSize)^numDimensions)
。
答案 2 :(得分:0)
现在,在编辑之后,这是绝对不同的问题。
当部件的顺序很重要(组合)时,这是将N号的所有分区生成为N + 1个部分的组合任务。德尔福代码(将值除以N得到你的&#39;坐标&#39;)。
注意有C(2n,n)这样的成分(C(6,3)= 20),其中C - 组合数。
var
Cmp: array of Integer;
N, NP, first, nonzero: Integer;
begin
N := 3;
NP := N + 1;
SetLength(Cmp, NP); //zero filled
Cmp[N] := N;
#output Cmp array
while Cmp[0] <> N do begin
first := Cmp[0];
Cmp[0] := 0;
nonzero := 1;
while Cmp[nonzero] = 0 do
Inc(nonzero);
Dec(Cmp[nonzero]);
Cmp[nonzero - 1] := first + 1;
#output Cmp array
end;
输出N = 2且N = 3
0 0 2
0 1 1
1 0 1
0 2 0
1 1 0
2 0 0
0 0 0 3
0 0 1 2
0 1 0 2
1 0 0 2
0 0 2 1
0 1 1 1
1 0 1 1
0 2 0 1
1 1 0 1
2 0 0 1
0 0 3 0
0 1 2 0
1 0 2 0
0 2 1 0
1 1 1 0
2 0 1 0
0 3 0 0
1 2 0 0
2 1 0 0
3 0 0 0
答案 3 :(得分:0)
我的一位朋友为这个问题提供了很好的解决方案。正如在这里的一些人,在他们的答案中提到的,这是一个问题,归结为产生写一个整数的所有方法&#39; m&#39;作为&#39; k&#39;的总和非负整数。这是一个link详细说明了这个问题。
结合Andy关于使用整数的反馈,这里是更新的java代码和一些注释。请不要这是我的朋友提供的解决方案的java改编:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class PointEnumeration {
static class Point {
//a list of integer where index i is the (i+1)'th dimension
List<Integer> dimensions;
Point(int step, int numDim){
this.dimensions = new ArrayList<>();
for(int i = 0; i < numDim; i++) {
this.dimensions.add(step);
}
}
Point(int step, Point p){
this.dimensions = new ArrayList<>();
this.dimensions.add(step);
this.dimensions.addAll(p.dimensions);
}
int get(int pos) {
return dimensions.get(pos);
}
}
private static List<Point> findPoints(int steps, int numDim){
if(numDim == 1){
//Only one dimension, add the `steps` to the only dimension
return Arrays.asList(new Point(steps, 1));
}
List<Point> result = new ArrayList<>();
if(steps == 0){
//Nothing left, create a point with all zeroes
return Arrays.asList(new Point(0, numDim));
}
//Iterate on the steps
for(int i = 0; i <= steps; i++){
//Recurse on the remaining steps and
//reduce the dimension by 1 (since this dimension will
// be handled in the next for-each loop)
List<Point> remaining = findPoints(steps-i, numDim-1);
for (Point point : remaining) {
//Append the i'th step to the remaining point
Point complete = new Point(i, point);
//This is a complete point for the i'th step
// and current dimension
result.add(complete);
}
}
return result;
}
public static void main(String[] args) {
float stepSize = 0.2f;
int numDim = 4;
int steps = (int) Math.ceil(1.0 / stepSize);
List<Point> res = findPoints(steps, numDim);
for (Point p : res) {
for (int coord : p.dimensions) {
//Convert integer steps to float value
System.out.print(String.valueOf(coord <= 0 ? 0.0f : (coord / (float) steps)) + ", ");
}
System.out.println(" ");
}
System.out.println("Total number of points =" + res.size());
}