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

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

    Returns6

    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

    Returns8

    • a{ 50, 10, 15,
      31, 20, 23, 7, 48, 5, 50 }
    • b{ 2, 5, 1, 8,
      3, 2, 16, 11, 9, 1 }
    • K3

    Returns124

    • a{ 2, 4, 10, 2,
      2, 22, 30, 7, 28 }
    • b{ 5, 26, 1, 2,
      6, 2, 16, 3, 15 }
    • K5

    Returns54

题解

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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-07 14:22:01

Floyd-Warshall+二进制枚举SRM 661 Div2 Medium: BridgeBuilding的相关文章

SRM 661 #DIV2

Problem Statement   You have a rectangular board that is placed vertically. The board is divided into a grid of unit square cells. Some grid cells contain obstacles and some cells contain a grain of sand. All other cells are currently empty. You are

DP SRM 661 Div2 Hard: ColorfulLineGraphsDiv2

Problem Statement Bob is going to create a graph with N nodes. The graph will be constructed in two steps. First, Bob will take N isolated vertices, label them 1 through N and color each of them using one of K colors. Then, Bob will add some directed

SRM 630 DIV2

SRM 630 DIV2 第一次TC,本来以为AK了,结果1000分还是被系统cha掉了,不过倒是也cha掉了房间其他人赚了不少 A:字符串长度才50,直接简单的模拟即可 B:结点个数才10,先做一边floyd,找出两两之间路径,然后暴力枚举选哪些点,判断可不可以,如果可以的话,记录下最大个数 C:一开始的做法是,构造出rank数组后,对于连续的一段,都放a,然后最后一个放b即可,以为这样构造出来的肯定是字典序最小的,结果被系统cha掉了. 正确做法:一开始先构造出sa数组,暴力枚举每个位置,非

SRM 638 Div2

2333... 由于TC参赛数太少,加上不断的fst 我都降到div2了. 还好做完就回div1了.. 250 水题 500 水题.. 直接bfs扩展就行了 注意判重,  我还用康托展开了真是多此一举.. 1000 这题理解错题意了..我说看别人代码怎么看着不对劲来着 不过还是非常容易的一道题 二进制枚举烧哪些叶子结点 然后对每种烧法 求最短路 求完最短路,枚举边 假设边的两个结点是u,v权值为w 就求最大的(dis[u]+dis[v]+w )/2就是烧完的时间 为啥这样呢 假设某边是最后被烧掉

UVa 818 切断圆环链(dfs+二进制枚举)

https://vjudge.net/problem/UVA-818 题意:有n个圆环,其中有一些已经扣在了一起.现在需要打开尽量少的圆环,使得所有圆环可以组成一条链,例如,有5个圆环,1-2,2-3,4-5,则需要打开一个圆环,如圆环4,然   后用它穿过圆环3和圆环5后再次闭合4,就可以形成一条链:1-2-3-4-5. 思路:从n个圆环中任意选择圆环,这就是枚举子集.所以这道题目可以用二进制枚举来做. 那么如何判断当前打开圆环是可行的呢?在去除打开的圆环后需要判断: ①:每个圆环的分支数都必

UVa818 Cutting Chains (二进制枚举)

链接:http://vjudge.net/problem/35523 分析:links记录初始圆环链的情况,然后二进制枚举编号为0~n-1的圆环哪个被打开了,一个圆环最多一个前驱和一个后继,所以judge判断如果有一个未打开的圆环同时和2个以上的未打开圆环相连就一定不能形成链,剪去.circle判断剩下的未打开圆环是否形成环,以及若未成环那么有多少条单链links_num,注意最后成链不用按顺序比如1->2->3...这样.然后判断一下打开的圆环数够不够把links_num条单链扣成一条链,若

POJ 2436 二进制枚举+位运算

题意:给出n头牛的得病的种类情况,一共有m种病,要求找出最多有K种病的牛的数目: 思路:二进制枚举(得病处为1,否则为0,比如得了2 1两种病,代号就是011(十进制就是3)),首先枚举出1的个数等于k的二进制数,然后跟所有的牛的代号一一比较,符合的           +1,找出其中和最大的:就是转换2进制麻烦,用位运算就好实现了,但是位运算不是很明白含义,明白了再补充: 知识点: 3 & 2 = 2,相同为1,不同为0, 011 & 010 = 010:(怎么利用的这个特点不明白):

1151 - Buy or Build(二进制枚举子集 + 并查集)

这题LRJ书上翻译的有问题,书上说两点之间的cost是两点的欧几里得距离,而题目要求两点的距离是两点欧几里得距离的平方. 其余就没什么好说的了,裸的并查集,需要注意的就是二进制枚举子集的问题. 二进制枚举子集: for(int i = 0 ; i < (1 << s) ; i++){ /*s是集合元素的个数*/ for(int j = 0 ; j < s ; j++){ if(!(s >> j) & 1) continue; else{ } } } 140548

topcoder SRM 618 DIV2 WritingWords

只需要对word遍历一遍即可 int write(string word) { int cnt = 0; for(int i = 0 ; i < word.length(); ++ i){ cnt+=word[i]-'A'+1; } return cnt; } topcoder SRM 618 DIV2 WritingWords,布布扣,bubuko.com