【问题标题】:Dynamic programing / Combinations without repetitions and order is not important动态规划/没有重复和顺序的组合并不重要
【发布时间】:2014-08-12 15:02:12
【问题描述】:

假设我们有一条长度为 L 的铁路。我们需要在这条铁路的第一公里和最后一公里之间放置 K 个服务站。 0公里和L公里的服务站已经免费建设。给定的是在这条铁路的每公里处建造一个服务站的价格,以及计算给定铁路长度的服务价格的方程式。

例如,我们有 4 公里的铁路,并获得在第 n 公里铁路建设一个车站的价格清单:

5 22 13

我们还有车站之间的服务方程式 - PRICE(len) = 2 * len*len + 3*len.

所以,我们需要建立1站,我们可以这样做:

1 公里 - 建筑费用为 5,PRICE(1)=5(0 到 1 公里的服务)+ PRiCE (3)=27(1 到 4 公里的服务)=> 37

2st km - 建筑费用 22,PRICE(2)=14(0 到 2 公里的服务)+ PRiCE (2)=14(服务从 2 到 4 公里)=> 50

3st km - 建筑费用 13,PRICE(3)=27(0 到 3 公里的服务)+ PRiCE (1)=5(3 到 4 公里的服务)=> 69

最好的选择是在第一公里建1站。

如果我们需要建设 2 个站点怎么办?

 |S|_|_|_|F|

 |S|1|2|_|F|  5+22+PRICE(1)+PRICE(1)+PRICE(2) = 5 + 22 + 5 + 5 + 14 = 51 
 |S|1|_|3|F|  5+13+PRICE(1)+PRICE(2)+PRICE(1) = 5 + 13 + 5 + 14 + 5 = 42
 |S|_|2|3|F|  22+13+PRICE(2)+PRICE(1)+PRICE(1) = 22 + 13 + 14 + 5 + 5 = 59

因此,最好的方法是在第一公里和第三公里放置两个车站。

我的任务是找到给定长度的最低价格、要建造的车站数量、在特定公里数和方程式上建造车站的价格。

我的想法是计算 len 表以了解维持特定长度的成本。例如,它是表:

+------+------+------+------+
| idx0 | idx1 | idx2 | idx3 |
+------+------+------+------+
|    0 |    5 |   14 |   27 |
+------+------+------+------+

然后我计算表格,其中包含在特定公里上建造任意两个站点的成本:

╔══════╦══════╦══════╦══════╦══════╗
║      ║ idx0 ║ idx1 ║ idx2 ║ idx3 ║
╠══════╬══════╬══════╬══════╬══════╣
║ idx0 ║      ║      ║      ║      ║
║ idx1 ║      ║    5 ║   32 ║   32 ║
║ idx2 ║      ║      ║   22 ║   40 ║
║ idx3 ║      ║      ║      ║   13 ║
╚══════╩══════╩══════╩══════╩══════╝

那么,我只需创建递归并像这样遍历:

 public static void recur(int cost, int level, int idx) {
        if (level == 0) {
            if (min > cost + len[delka - idx]) {
                min = cost + len[delka - idx];
                System.out.println(min);
            }

        }
        if (level > 0 && cost < min) {
            for (int i = idx; i <= delka - level; i++) {
                recur(cost + d[idx][i], level - 1, i);                
        }
    }

我以 0 成本开始调用它,level 是要建造的车站数量,idx 是指向最后建造车站的指针。

最大的问题是,例如对于 L = 200 和 50 个站,有 4.538583779232459e+47 组合,我认为我在每个组合中都做得不好。当然我剪了一些东西cost &lt; min,但它仍然非常慢,我想我只是错过了一些东西。

我觉得我可以把它分解成子问题。

捷克语原问题:https://cw.felk.cvut.cz/courses/a4b33alg/task.php?task=servis

【问题讨论】:

    标签: java algorithm combinations dynamic-programming combinatorics


    【解决方案1】:

    首先,请注意,对于任何位置 x,如果我们已经计算了将最后一个站点放在第 y 公里的结果,y

    示例代码如下:

    int memo[MAX_KM][MAX_KM][MAX_STATION];
    bool seen[MAX_KM][MAX_KM][MAX_STATION]; // if seen[km][pos_of_last_station][station_remaining] is true 
                                             // then this subproblem has already been solved. No need to solve it again
    
    int dp(int KM, int pos_of_last_station, int station_remaining) {
        if(KM == MAX_KM + 1) {
            // reached the end
            int len = (MAX_KM - pos_of_last_station);
            return 2 * len * len + 3 * len;
        }
    
        if(seen[KM][pos_of_last_station][station_remaining]) {
            // this sub problem has already been solved
            return memo[KM][pos_of_last_station][station_remaining];
        }
        int ret = 2e9; // some large value
        if(station_remaining > 0) {
    
            // trying establishing a station on the current position
            int len = KM - pos_of_last_station;
            ret = min(ret, dp(KM + 1, KM, station_remaining - 1) + (2 * len * len + 3 * len) + cost[KM] );  // assuming cost[KM] is the cost to establish a station on KMth kilometer
        }
        ret = min(ret, dp(KM + 1, pos_of_last_station, station_remaining) );
        seen[KM][pos_of_last_station][station_remaining] = true; // sub problem visited
        memo[KM][pos_of_last_station][station_remaining] = ret;  // storing the result for future utilization
    
        return ret;
    
    }
    

    复杂性分析:将需要 O(MAX_KM * MAX_KM * MAX_STATION) 时间和空间

    警告:代码未经测试

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-13
      相关资源
      最近更新 更多