选择点,使得x坐标的总和= y坐标的总和

时间:2013-11-30 15:11:04

标签: java algorithm

我有一个Point的数组。我需要从中选择一个点子集,这样点的x坐标之和=点的y坐标之和。 如果存在许多这样的子集,则需要具有最大x坐标总和的子集。 需要报告x坐标的总和。

我写了一个强力递归方法,它测试所有可能性。

Point[] a = new Point[n];
// ...
private int rec(int i, int x, int y) {
    if (i == n - 1) {
        if (x + a[i].x == y + a[i].y) return x + a[i].x;
        return (x == y) ? x : -1;
    }
    return Math.max(rec(i + 1, x, y), rec(i + 1, x + a[i].x, y + a[i].y));
}

答案是rec(0, 0, 0)

我的问题是:

1)是否有针对此的动态编程解决方案?
2)如果是,可以请任何人解释

4 个答案:

答案 0 :(得分:4)

我有一点好(比蛮力)算法。

  1. 将所有坐标分为三组:
     1: {(x,y): x>y}, 2: {(x,y):x==y}, 3:{(x,y): x lower-than y}
  2. 集合2必须始终包含在解决方案中。
  3. 来自1定义net=x-y的每个(x,y)和每个(x,y)形式3定义net=y-x
  4. 检查您可以net中的1net中的3检索所有可能的值。
  5. 然后基于最大匹配,很容易构建解决方案。
  6. 有意义吗?

答案 1 :(得分:4)

对于每个点,将其值设置为x - y

现在我们需要找到一组其值总和为0的点。

这正是the subset sum problem

它是NP-complete(即,对于问题的一般情况,没有已知的多项式时间算法),但是存在伪多项式时间DP解决方案,其在Wikpedia上给出,在上面链接。简要总结:

  

我们将函数Q(i,s)定义为

的值(truefalse
there is a nonempty subset of x1, ..., xi which sums to s
     

然后我们有以下重复:

Q(1,s) := (x1 == s)
Q(i,s) := Q(i − 1, s) or (xi == s) or Q(i − 1, s − xi)   for A ≤ s ≤ B

答案 2 :(得分:2)

除非有未说明的约束,否则问题是NP-Hard通过Subset-Sum的多项式时间减少,NP-Complete问题。

Subset-Sum的一种决策形式在给定一组整数X和整数s的情况下,将任何非空子集求和为s。

对于X的每个元素,构造一个Point,其x值是元素,其y值为零。构造一个额外的Point,其x值为0,其y值为s。

如果应用于该组点的等和问题的结果为0或-1,则拒绝子集求和问题。如果结果是s,则接受subset-sum。

假设P!= NP,或者至少我们没有任何NP-Hard问题的多项式算法,则没有已知的多项式时间算法来解决你的问题。

答案 3 :(得分:1)

只是尝试在java中编写代码,我觉得有用:

所有我的

diffOfCoordinates[i] = Xi - Yi

list将获得最高分。

public void fun(int[] diffOfCoordinates, int indexA, int[] b, int indexB, int sum, List<Integer> list){
       if(indexA == diffOfCoordinates.length){
           if(sum==0){
               if(list.size()<indexB){
                   list.clear();
                   for(int i=0;i<indexB;i++){
                       list.add(b[i]);
                   }
               }
           }
           return;
       }
       b[indexB] = diffOfCoordinates[indexA];
       fun(diffOfCoordinates, indexA+1, b, indexB+1, sum+diffOfCoordinates[indexA], list);
       fun(diffOfCoordinates, indexA+1, b, indexB, sum, list);
   }