骆驼过桥dp二分
题意是n(<=8)只骆驼 有重量 要过桥 桥分成好几段 每段都有长度和承受重量 问第一只骆驼和最后一只骆驼 最小距离 多少能过桥
给定思路:骆驼过桥 如果 过长度相同的桥 那么只看承受重量最低的就好了
如果过重量相同的桥 那么只看长度最长的桥就好了
所以 遇到 桥段a 的长度比 桥段b 的长度 短 而且 桥段 a的承受能力 比 桥段 b的承受能力 大 那么 桥段a就是废桥
所以由此考虑 我们只需要把 把长度当作 第一首选 重量当作第二首选进行排序就好了 如果 后面长度大 且 承受能力 比 他小 那么前一个桥段 就是废桥
我们就把他 等于 后面桥段的 承受能力 就好了 这样子看 序列 就是 越往后面
桥段又长承受能力又大 就可以进行二分了
因为骆驼最多8只 我们只需要dfs遍历骆驼的位置即可
#include<iostream>
#include<cstring>
#include<algorithm>
#define endl "\n"
using namespace std;
const int N = 1e5 + 10;
int a[10];
struct node{
int l,w;
bool operator <(const node &p)const{
if(l == p.l) return w < p.w;
else return l < p.l;
}
}c[N];
int n,m;
int minn;
int b[15];
int check(int x){
int l = 0,r = m + 1;
int res = 0;
while(l + 1 < r){
int mid = l + r >> 1;
if(x > c[mid].w){
l = mid;
}
else r = mid;
}
return c[l].l;
}
int dp[10],g[10];
int res = 0x3f3f3f3f;
void solve(){
memset(dp,0,sizeof dp);
for(int i = 1; i <= n; i++){
b[i] = b[i - 1] + a[g[i]];
}
for(int i = 2; i <= n; i++){
for(int j = i - 1; j >= 1; j--){
int len = check(b[i] - b[j - 1]);
dp[i] = max(dp[i],dp[j] + len);
}
}
res = min(res,dp[n]);
}
int flag[10];
void dfs(int x){
if(x == n){
solve();
return;
}
for(int i = 1; i <= n; i++){
if(!flag[i]){
flag[i] = 1;
g[x + 1] = i;
dfs(x + 1);
flag[i] = 0;
}
}
}
int main(){
cin >> n >> m;
minn = 0x3f3f3f3f;
int maxn = 0;
for(int i = 1; i <= n; i++){
cin >> a[i];
maxn = max(maxn,a[i]);
}
bool st = true;
for(int i = 1; i <= m; i++){
cin >> c[i].l >> c[i].w;
}
sort(c + 1,c + m + 1);
for(int i = m; i >= 1; i--){
minn = min(minn,c[i].w);
c[i].w = minn;
}
for(int i = 1; i <= n; i++){
if(a[i] > minn){
st = false;
break;
}
}
if(!st) cout << "-1" << endl;
else{
dfs(0);
cout << res << endl;
}
return 0;
}