Floyd-Warshall+二进制枚举SRM 661 Div2 Medium: BridgeBuilding

4 篇文章 0 订阅
1 篇文章 0 订阅

SRM 661-Medium: BridgeBuildingDiv2 

Problem Statement

You have two rows of nodes. Each row contains N nodes, numbered 0 through N-1 from the left to the right.

Within each row, adjacent nodes are already connected by edges. You are given the lengths of these edges as int[]s a and b, each containing N-1 elements. For each valid i,a[i] is the length of the edge between nodes i and (i+1) in the top row, and b[i] is the length of the edge between nodes i and (i+1) in the bottom row.

You want to add exactly K new edges to this graph. Each of the new edges must be vertical -- i.e., it must connect some vertex i in the top row to the vertex i in the bottom row. All new edges will have length 0.

By adding the K new edges we will produce a connected graph. The diameter of this graph is the maximum of all shortest distances among pairs of its nodes. In other words, the diameter is the smallest number D such that it is possible to travel from any node to any other node using a path of length D or less.

Given ab, and the int K, compute and return the smallest possible diameter of the resulting graph.

Definition

  • ClassBridgeBuildingDiv2
  • MethodminDiameter
  • Parametersvector<int> , vector<int> , int
  • Returnsint
  • Method signatureint minDiameter(vector<int> a, vector<int> b, int K)
(be sure your method is public)

Limits

  • Time limit (s)2.000
  • Memory limit (MB)256

Constraints

  • N will be between 2 and 11, inclusive.
  • a,b will contain exactly N-1 elements each.
  • K will be between 1 and N, inclusive.
  • Each element of a,b will be between 1 and 50, inclusive.

Test cases

    • a{ 2, 1, 1, 1, 2 }
    • b{ 1, 9, 1, 9, 1 }
    • K4
    Returns 6

    One example of an optimal solution is to draw the bridges as follows:

    • a{ 1, 50, 1, 50, 1, 50, 1, 50 }
    • b{ 50, 1, 50, 1, 50, 1, 50, 1 }
    • K9
    Returns 8
    • a{ 50, 10, 15, 31, 20, 23, 7, 48, 5, 50 }
    • b{ 2, 5, 1, 8, 3, 2, 16, 11, 9, 1 }
    • K3
    Returns 124
    • a{ 2, 4, 10, 2, 2, 22, 30, 7, 28 }
    • b{ 5, 26, 1, 2, 6, 2, 16, 3, 15 }
    • K5
    Returns 54
题解

All bridges must be vertical. This means that there are only 

N  possible locations for the bridges. With a given  K , this leads to (NK)  (Where  (NK) is the binomial coefficient) total options for ways to assign  K  bridges to  N  positions. For  N=11,K=6

 (The worst case) we will have 462 options in total. Let's try them all. We can do this with backtracking or with bit masks. Now we just need to, for each combination of bridges, calculate the diameter

The diameter

In order to calculate the diameter, we need to know the maximum pairwise distance between any two distinct vertices in the graph. I recommend to use Floyd-Warshall algorithm as its output will be a table of all pair-wise distances. It is  O(|V|3)  , which we repeat for each of the (at most 462) options for sets. Note that the number of vertices  |V|  is actually  2N , this means that  |V|3  is  8N3 . It is still very appropriate given the small constraints.

int minDiameter(vector<int> a, vector<int> b, int K)
{
    const int INF = 1000000;
    int res = INF;
    int n = a.size() + 1;
    // the idea is we use bit masks to generate all subsets of a set of N
    // elements. Then we count the number of 1 bits so only those with K
    // elements are checked.
    for (int mask = 0; mask < (1<<n); mask++) {
        if (__builtin_popcount(mask) == K) {
 
            // One way to simplify implementation 
             
            // The distances array.
            vector<vector<int>> dist(2*n, vector<int>(2*n, INF));
             
            for (int i = 0; i < n; i++) {
                if (mask & (1<<i)) {
                    //bridge
                    dist[i][i + n] = 0;
                    dist[i + n][i] = 0;
                }
            }
            // top
            for (int i = 0; i < n - 1; i++) {
                dist[i][i+1] = a[i];
                dist[i+1][i] = a[i];
            }
            // bottom
            for (int i = 0; i < n - 1; i++) {
                dist[i+n][i+n+1] = b[i];
                dist[i+n+1][i+n] = b[i];
            }
            // Floyd-Warshall
            for (int k = 0; k < 2*n; k++) {
                for (int i = 0; i < 2*n; i++) {
                    for (int j = 0; j < 2*n; j++) {
                        dist[i][j] = std::min( dist[i][j], dist[i][k] + dist[k][j]);
                    }
                }
            }
            // Of known distances, pick the largest:
            int max_dist = 0;
            for (int i = 0; i < 2*n; i++) {
                for (int j = i + 1; j < 2*n; j++) {
                    max_dist = std::max(max_dist, dist[i][j]);
                }
            }
            res = std::min(res, max_dist);
        }
    }
    return res;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>