105-C Camels and Bridge
Time Limit: 2 sec / Memory Limit: 1024 MB
Score : 500500 points
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≤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
题意
有N只骆驼,每只骆驼有各自的重量,所有骆驼通过M段组成的的桥,每段桥有长度和 承重力,问第一只和最后一只骆驼最短的相隔的距离可以顺利通过这座桥。
思路
骆驼最多有8只
所以暴力全排列,枚举每个排列顺序
dp逐一求解。
dp[i]=max( dp[j] + length(j,i) );
length(i,j) 表示第 j 只到第 i 只骆驼过桥的最短距离
易得:
①两段桥如果同长,则舍弃承重力强的
②两段桥如果同承重力,则舍弃长度短的
(因为 若长度相同,显然影响结果的是承重力弱的 ; 若承重力相同,假设通过较短的桥得到了一段骆驼的最短距离要>=较短桥的长度,但此时并没有保证这个长度一定大于较长的桥的长度,所以这段骆驼会同时出现在较长的桥上,桥会塌陷,所以舍弃较短的桥段)
要通过所有的桥,对桥按长度增和承重力增排序
预处理桥,若桥的长度短或相同但承重力强,这段桥的承重力更改为比它长的桥的最小的承重力(即①②);
这样可以得到长度越长承重力越大的桥。
可以通过二分得到length()
二分找最后一个小于当前几只骆驼重量的桥的长度
要保证答案最小。
代码
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int M=1e5+7;
const int V=1e8;
int n,m;
int Ca[10],Capos[10];
int Sum[10];
int dp[10];
pair<int,int>Br[M];
int Init()
{
sort(Br+1,Br+m+1);
int minn=Br[m].second;
for(int i=m-1;i>=1;i--)
{
minn=min(minn,Br[i].second);
if(Br[i].second>minn)
{
Br[i].second=minn;
}
}
for(int i=1;i<=n;i++)
Capos[i]=i;
return minn;
}
int length(int x)
{
int l=1,r=m;
int mid=0;
while(l<=r)
{
mid=(l+r)>>1;
if(x>Br[mid].second)
l=mid+1;
else
r=mid-1;
}
return Br[r].first;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>Ca[i];
for(int i=1;i<=m;i++) {cin>>Br[i].first>>Br[i].second;}
int minn=Init();
for(int i=1;i<=n;i++)
{
if(Ca[i]>minn)
{
cout<<-1<<endl;
return 0;
}
}
int ans=INF;
do
{
Sum[1]=Ca[Capos[1]];
Sum[0]=0;
for(int i=2;i<=n;i++)
{
Sum[i]=Sum[i-1]+Ca[Capos[i]];
}
for(int i=1;i<=n;i++)
dp[i]=0;
for(int i=2;i<=n;i++)
{
for(int j=i-1;j>=1;j--)
{
dp[i]=max(dp[i],dp[j]+length(Sum[i]-Sum[j-1]));
}
}
ans=min(ans,dp[n]);
}while(next_permutation(Capos+1,Capos+n+1));
cout<<ans<<endl;
return 0;
}