题意
给出 (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;
}