AtCoder Regular Contest 105-C

题意

给出 (N) 只骆驼,每只骆驼有一个重量 (w_i)。有一座桥,由 (M) 个部分组成,每个部分有一个长度 (l_i) 和一个重量 (v_i) 。求出使得骆驼可以通过桥的队伍的最短长度,为整数。

  • (2≤N≤8)
  • (1≤M≤10^5)
  • (1≤w_i,l_i,v_i≤10^8)

分析

可以发现 (N) 很小,可以枚举出骆驼的全部可能排列。每一种排列中,对于任意位置 (i)(j)(i<j)),我们可以求出二者之间的最短距离,即我们可以建立一个有向无环图。求出此图中从点 (1) 到点 (N) 的最长路的长度,即可得到满足任意两头骆驼之间的距离要求的队伍的最短长度,求出所有排列的最长路,取最小即为答案。

复杂度:(O(N!N^2log_2M))

代码

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int N=1e5+5;
pii bridge[N];
int w[12],a[12],len[N],b[N],sum[12];
ll dp[12];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    int maxn=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&w[i]);
        maxn=max(maxn,w[i]);
    }
    for(int i=1;i<=m;i++) scanf("%d%d",&bridge[i].second,&bridge[i].first);
    sort(bridge+1,bridge+1+m);
    if(bridge[1].first<maxn)
    {
        printf("-1
");
        return 0;
    }
    len[0]=0;
    for(int i=1;i<=m;i++) len[i]=max(len[i-1],bridge[i].second);
    for(int i=1;i<=m;i++) b[i]=bridge[i].first;
    for(int i=1;i<=n;i++) a[i]=i;
    ll ans=1e15;
    do
    {
        dp[1]=0;
        for(int i=1;i<=n;i++)
            sum[i]=sum[i-1]+w[a[i]];
        for(int i=2;i<=n;i++)
        {
            dp[i]=0;
            for(int j=1;j<i;j++)
            {
                int tmp=sum[i]-sum[j-1];
                int p=lower_bound(b+1,b+1+m,tmp)-b-1;
                dp[i]=max(dp[i],dp[j]+len[p]);
            }
        }
        ans=min(ans,dp[n]);
    }
    while(next_permutation(a+1,a+1+n));
    printf("%lld
",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/1024-xzx/p/13807349.html