AtCoder - ARC105_C Camels and Bridge (dp + 二分)

Problem Statement

 

There are NN camels numbered 11 through NN.

The weight of Camel ii is wiwi.

You will arrange the camels in a line and make them cross a bridge consisting of MM parts.

Before they cross the bridge, you can choose their order in the line - it does not have to be Camel 11, 22, ……, NN from front to back - and specify the distance between each adjacent pair of camels to be any non-negative real number. The camels will keep the specified distances between them while crossing the bridge.

The ii-th part of the bridge has length lili and weight capacity vivi. If the sum of the weights of camels inside a part (excluding the endpoints) exceeds vivi, the bridge will collapse.

Determine whether it is possible to make the camels cross the bridge without it collapsing. If it is possible, find the minimum possible distance between the first and last camels in the line in such a case.

It can be proved that the answer is always an integer, so print an integer.

Constraints

 

  • All values in input are integers.
  • 2≤N≤82≤N≤8
  • 1≤M≤1051≤M≤105
  • 1≤wi,li,vi≤1081≤wi,li,vi≤108

Input

 

Input is given from Standard Input in the following format:

NN MM
w1w1 w2w2 ⋯⋯ wNwN
l1l1 v1v1
⋮⋮
lMlM vMvM

Output

 

If the bridge will unavoidably collapse when the camels cross the bridge, print -1. Otherwise, print the minimum possible distance between the first and last camels in the line when the camels cross the bridge without it collapsing.

Sample Input 1

 

3 2
1 4 2
10 4
2 6

Sample Output 1

 

10
  • It is possible to make the camels cross the bridge without it collapsing by, for example, arranging them in the order 11, 33, 22 from front to back, and setting the distances between them to be 00, 1010.
    • For Part 11 of the bridge, there are moments when only Camel 11 and 33 are inside the part and moments when only Camel 22 is inside the part. In both cases, the sum of the weights of camels does not exceed 44 - the weight capacity of Part 11 - so there is no collapse.
    • For Part 22 of the bridge, there are moments when only Camel 11 and 33 are inside the part and moments when only Camel 22 is inside the part. In both cases, the sum of the weights of camels does not exceed 66 - the weight capacity of Part 22 - so there is no collapse.
  • Note that the distance between two camels may be 00 and that camels on endpoints of a part are not considered to be inside the part.

Sample Input 2

 

2 1
12 345
1 1

Sample Output 2

 

-1
  • Print -1 if the bridge will unavoidably collapse.

Sample Input 3

 

8 1
1 1 1 1 1 1 1 1
100000000 1

Sample Output 3

 

700000000

Sample Input 4

 

8 20
57 806 244 349 608 849 513 857
778 993
939 864
152 984
308 975
46 860
123 956
21 950
850 876
441 899
249 949
387 918
34 965
536 900
875 889
264 886
583 919
88 954
845 869
208 963
511 975

Sample Output 4

 

3802

题意:

现有 n 头骆驼排队过 m 段连续的桥,给出每头骆驼的重量、每段桥的最大承重和长度,求从第一头骆驼到第 n 头骆驼的最短距离,骆驼排队的顺序可以更改。

思路:

dp[i] 表示第 i 头骆驼到第1头骆驼的最短距离,转移方程:dp[i] = max(dp[i], dp[j] + len)

len表示第 j 头骆驼到第 i 头骆驼可以安全过桥需要保持的最短距离

----------------------------------------------------------------------
Q:为什么取max?

A:dp[j] + len 仅保证了骆驼 j~i 可以安全过桥,要使所有骆驼都可以安全过桥,就要取最短距离的最大值

----------------------------------------------------------------------

二分求len。

准备工作:把所有桥按第一关键字长度、第二关键字承重排序,长度很长、承重很小的桥限制了长度很短、承重很大的桥的承重,所以排序前直接将每个桥的承重修改为长度更长的桥的最小承重。

二分最短距离,check当前桥的承重是否 > 第 j 只 ~ 第 i 只骆驼的总重量,返回可容纳这些骆驼的最短的桥

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 1e5 + 10;
const int M = 5e4 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

int w[10], res, dp[10], sum[10], n, m, b[10];
bool vis[10];
struct node {
    int w, l;
    bool operator < (const node &a) {
        if(l == a.l) return w < a.w;
        else return l < a.l;
    }
} s[N];

///这俩二分都对
int lower_b(int x) {
    int l = 0, r = m + 1;
    while(l + 1 < r) {
        int mid = (l + r) >> 1;
        if(x > s[mid].w) l = mid;
        else r = mid;
    }
    return s[l].l;
}

//int lower_b(int x) {
//    int l = 1, r = m, res = 0;
//    while(l <= r) {
//        int mid = (l + r) >> 1;
//        if(x > s[mid].w) {
//            res = s[mid].l;
//            l = mid + 1;
//        }
//        else r = mid - 1;
//    }
//    return res;
//}

void solve() {
    memset(dp, 0, sizeof(dp));
    for(int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + w[b[i]];
    for(int i = 2; i <= n; ++i) {
        for(int j = i - 1; j >= 1; --j) {
            int tmp = sum[i] - sum[j - 1];
            int len = lower_b(tmp);
            dp[i] = max(dp[i], len + dp[j]);
        }
    }
    res = min(res, dp[n]);
}

void dfs(int now) {
    if(now == n) {
        solve();
        return ;
    }
    for(int i = 1; i <= n; ++i) {
        if(!vis[i]) {
            vis[i] = 1;
            b[now + 1] = i;
            dfs(now + 1);
            vis[i] = 0;
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) scanf("%d", &w[i]);
    for(int i = 1; i <= m; ++i) scanf("%d%d", &s[i].l, &s[i].w);
    sort(s + 1, s + m + 1);
    int minn = inf;
    for(int i = m; i >= 1; --i) {
        minn = min(minn, s[i].w);
        s[i].w = minn;
    }
    for(int i = 1; i <= n; ++i) {
        if(w[i] > minn) {
            printf("-1\n");
            return 0;
        }
    }
    res = inf;
    dfs(0);
    printf("%d\n", res);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43871207/article/details/109190106
今日推荐