题目描述
There are n people who want to get to the top of a building which has only one elevator. You know the weight of each person and the maximum allowed weight in the elevator. What is the minimum number of elevator rides?
输入
The first input line has two integers n and x: the number of people and the maximum allowed weight in the elevator.
The second line has n integers w1,w2,...,wn: the weight of each person.
Constraints
1 ≤ n ≤ 20
1 ≤ x ≤ 109
1 ≤ wi ≤ x
输出
Print one integer: the minimum number of rides.
样例输入
4 10 4 8 6 1样例输出
2
**题目大意:**n个人,只有一台电梯,电梯最大载重为x,为最少需要上几趟
**思路:**n<=20,想到状压dp,定义mask状态,0表示不选,1表示选,用dp[mask]表示选择mask状态的人时,需要的最少趟数,由于每一趟都是最少的趟数,在新添加一个人时,只需要考虑它能不能上最后那一趟电梯,所以还需要记录最后一趟的剩余载重。
另外注意,状压dp中的状态更新后的current可能是由多个mask更新而来的,所以需要最后在与之前的dp[current]进行比较,而不是直接进行更新
cpp
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int w[20];
int dp[1<<20];//最少趟数
int remain[1<<20];//最后一趟还能载多重
int main(){
int n,x;cin>>n>>x;
for (int i=0;i<n;i++)
cin>>w[i];
memset(dp,0x3f,sizeof(dp));
dp[0]=0,remain[0]=0;
for (int mask=0;mask<(1<<n);mask++){
for (int i=0;i<n;i++){
if(mask&(1<<i))
continue;
int current=mask|(1<<i);
int tdp,tremain;
if(remain[mask]>=w[i]){
tdp=dp[mask];
tremain=remain[mask]-w[i];
}
else{
tdp=dp[mask]+1;
tremain=x-w[i];
}
if(tdp<dp[current]||(tdp==dp[current]&&tremain>remain[current])){
dp[current]=tdp;
remain[current]=tremain;
}
}
}
cout<<dp[(1<<n)-1];
}