问题描述
一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍在桥上的人都不能超过一定的限制.
所以这只队伍过桥时只能分批过,当一组全部过去时,下一组才能接着过.
队伍里每个人过桥都需要特定的时间,当一批队员过桥时时间应该算走得最慢的那一个,每个人也有特定的重量,
我们想知道如何分批过桥能使总时间最少.
输入格式
第一行两个整数: w,nw,n 分别表示 桥能承受的最大重量(100<=w<=400100<=w<=400) 和 nn队员总数(1<=n<=161<=n<=16).
接下来nn行每行两个整数tt和分别表示每个队员过桥所需时间(1<=t<=501<=t<=50) 和 该队员的重量(10<=w<=10010<=w<=100).
输出格式
输出一个数表示最少的过桥时间.
f[i]f[i]表示在ii的二进制状态下全部过桥所需要的最少时间。
设是状态SS的一个子集,那么状态一定是通过状态S1S1与状态S2S2转移过来的,S1∪S2=SS1∪S2=S。
方程表示为:
f[S]=min(f[S1]+MaxT[S2]),SumW[S]<=Wf[S]=min(f[S1]+MaxT[S2]),SumW[S]<=W
其中MaxT[S]MaxT[S]表示的是SS状态下的人通过桥的最长时间,表示的是SS状态下的人的重量之和。
预处理,然后枚举集合与子集。
#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;
}
本文介绍了一种使用动态规划解决特定过桥问题的方法,旨在找出使全体队员以最短时间过桥的策略。考虑了队员数量、重量及桥的承载限制等因素。

被折叠的 条评论
为什么被折叠?



