问题描述
一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍在桥上的人都不能超过一定的限制.
所以这只队伍过桥时只能分批过,当一组全部过去时,下一组才能接着过.
队伍里每个人过桥都需要特定的时间,当一批队员过桥时时间应该算走得最慢的那一个,每个人也有特定的重量,
我们想知道如何分批过桥能使总时间最少.
输入格式
第一行两个整数: 分别表示 桥能承受的最大重量( ) 和 队员总数( ).
接下来 行每行两个整数 和 分别表示每个队员过桥所需时间( ) 和 该队员的重量( ).
输出格式
输出一个数表示最少的过桥时间.
表示在 的二进制状态下全部过桥所需要的最少时间。
设 是状态 的一个子集,那么状态 一定是通过状态 与状态 转移过来的, 。
方程表示为:
其中 表示的是 状态下的人通过桥的最长时间, 表示的是 状态下的人的重量之和。
预处理 ,然后枚举集合与子集。
#include <bits/stdc++.h>
using namespace std;
const int Inf=1e9;
int N,M,T,C[17],W[17],DP[1<<17],Sum[1<<17],MaxT[1<<17];
int main(){
int I,J,K,S1,S2;
scanf("%d%d",&M,&N);
for(I=1;I<=N;I++){
scanf("%d%d",&C[I],&W[I]);
}T=(1<<N)-1;
for(I=1;I<=T;I++){
for(J=1;J<=N;J++){
if((I>>(J-1)&1)==1){
Sum[I]+=W[J];
MaxT[I]=max(MaxT[I],C[J]);
}
}
}
for(I=1;I<=T;I++){
DP[I]=Inf;
for(S1=I;S1;S1=(S1-1)&I){
S2=I^S1;
if(Sum[S1]<=M){
DP[I]=min(DP[I],DP[S2]+MaxT[S1]);
}
}
}
printf("%d",DP[T]);
return 0;
}