使用动态规划选择最近对的算法

我一直试图解决我教授给我的这个问题,但无法做出正确的解决方案.以下是问题所在

问题:
矩形电路板具有两个平行的侧面,它们之间具有宽度W.在板的上侧有m个端子,在下侧有n个端子(n 1< U [2]< ……< U [m]分别是从板的左端到上侧的m个端子的距离.设L 1< L [2]< ……< L [n]分别是从板的左端到下侧的n个端子的距离.现在,我们需要从上侧的m个端子中选择n个端子,分别通过n个直线段连接到下侧的n个端子,使得n个线段的总长度最小化.下图说明了m = 8和n = 4的问题. 《使用动态规划选择最近对的算法》

(a)证明在最佳解决方案中,任何两个线段都不会相交.

(b)设计O(mn)动态编程算法来解决这种最小化问题.您需要定义子问题,显示归纳公式,初始条件和伪代码.您可以使用d(i,j)表示U [i]和L [j]之间的距离,1≤i≤m,1≤j≤n. (可以省略d(i,j)=)的计算.

我的方法:

对于上述问题,我的方法是首先制作一个矩阵d(i,j),其中i是底部的终端,j是顶部的终端. d(i,j)具有距任意两个电路的所有距离.然后迭代每一行,我将找到最小距离并标记相应的终端.但我不确定如果顶部电路都在极右侧,这将会起作用.所以任何人都可以为我提供更好的方法.

最佳答案 我编写了一个使用memoisation的递归动态编程解决方案,复杂度为O(mn),在每个递归级别,我们可以选择加入U []数组中定义的当前点和L []中定义的点数组,或者我们可以继续前进而不这样做:

#include<iostream>
#define INF 1e9

using namespace std;

int n, m, d[100][100], dp[100][100];

int solve(int idx1, int idx2){
    if(idx1 > m){
        if(idx2 < n) return INF;
        else return 0;
    }
    if(idx2 > n) return 0;
    if(dp[idx1][idx2] != -1) return dp[idx1][idx2];

    int v1, v2;

    //include current
    v1 = solve(idx1 + 1, idx2 + 1) + d[idx1][idx2];

    //do not include current
    v2 = solve(idx1 + 1, idx2);

    return dp[idx1][idx2] = min(v1, v2);
}

int main(){

    //enter the the distances

    for(int i = 0;i < 100;i++) for(int j = 0;j < 100;j++) dp[i][j] = -1;
    cout << solve(1, 1) << endl;
    return 0;
}

对于你的问题的(a)部分,让我们假设2个线段相交,那么我们就不能有一个最优解,因为如果我们只是交换L []数组定义的线段的2个端点那么距离会减少,从而为我们提供更好的解决方案.

点赞