AtCoder Regular Contest 105 C - Camels and Bridge

题目链接
题目描述
有n只骆驼过m桥,第i只骆驼负重\(w_i\),第i座桥的长度为\(l_i\),最大负重为\(v_i\),问骆驼队伍长度最短为多少可以通过所有的桥。
思路
n的数据范围很小,可以暴力解决。根据桥的长度从大到小预处理一下其能承受的重量。
\(dp[i]\)表示从第一只骆驼到第i只骆驼的最短距离。
\(dp[i] = max(dp[j] + len, dp[i])\),len表示第j只骆驼到第i只骆驼的最短距离。寻找len的过程中就是在预处理的桥中二分一下第j只到第i只骆驼的重量所返回的最短桥的长度。
代码

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
#define int LL
const int N = 1e5 + 10;

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

int find(int x) {
    int l = 1, r = m;
    int res = 0;
    while(l <= r) {
        int mid = l + r >> 1;
        if(x > a[mid].v) {
            res = a[mid].l;
            l = mid + 1;
        } else r = mid - 1;
    }
    return res;
}

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

void dfs(int cnt) {
    if(cnt == n) {
        work();
        return;
    }
    for(int i = 1; i <= n; i++) {
        if(!vis[i]) {
            vis[i] = true;
            b[cnt + 1] = i;
            dfs(cnt + 1);
            vis[i] = false;
        }
    }
}

void solve() {
    scanf("%lld%lld", &n, &m);
    for(int i = 1; i <= n; i++) {
        scanf("%lld", &w[i]);
    }
    for(int i = 1; i <= m; i++) {
        scanf("%lld%lld", &a[i].l, &a[i].v);
    }
    sort(a + 1, a + 1 + m);
    int mn = 1e9;
    for(int i = m; i >= 1; i--) {
        mn = min(mn, a[i].v);
        a[i].v = mn;
    }
    for(int i = 1; i <= n; i++) {
        if(mn < w[i]) {
            puts("-1");
            return;
        }
    }
    res = 2e18;
    dfs(0);
    printf("%lld\n", res);
}

signed main() {
//    freopen("in.txt", "r", stdin);
//    int t; scanf("%d", &t); while(t--)
    solve();
}

posted @ 2020-10-13 17:26  这知识他不进我的脑子  阅读(211)  评论(0编辑  收藏  举报