BZOJ P2071 「POI2004」过桥【状态压缩】

本文介绍了一种使用动态规划解决特定过桥问题的方法,旨在找出使全体队员以最短时间过桥的策略。考虑了队员数量、重量及桥的承载限制等因素。

问题描述

一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍在桥上的人都不能超过一定的限制.
所以这只队伍过桥时只能分批过,当一组全部过去时,下一组才能接着过.
队伍里每个人过桥都需要特定的时间,当一批队员过桥时时间应该算走得最慢的那一个,每个人也有特定的重量,
我们想知道如何分批过桥能使总时间最少.

输入格式

第一行两个整数: wnw,n 分别表示 桥能承受的最大重量(100<=w<=400100<=w<=400) 和 nn队员总数(1<=n<=161<=n<=16).
接下来nn行每行两个整数ttw分别表示每个队员过桥所需时间(1<=t<=501<=t<=50) 和 该队员的重量(10<=w<=10010<=w<=100).

输出格式

输出一个数表示最少的过桥时间.


f[i]f[i]表示在ii的二进制状态下全部过桥所需要的最少时间。

S1是状态SS的一个子集,那么状态S一定是通过状态S1S1与状态S2S2转移过来的,S1S2=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状态下的人通过桥的最长时间,SumW[S]表示的是SS状态下的人的重量之和。

预处理MaxT[]SumW[],然后枚举集合与子集。

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值