【题解】P3052 [USACO12MAR]摩天大楼里的奶牛Cows in a Skyscraper

\(Description:\)

给出n个物品,体积为w[i],现把其分成若干组,要求每组总体积<=W,问最小分组。

\(Sample\) \(Input:\)

4 10
5
6
3
7 3

\(Sample\) \(Output:\)

3

\(Hint:\)

\(n<=18\)

\(Solution:\)

喵的,如果这题数据范围再小一点,我就水过去了。。。

暴力上来就写了PRZ的做法,拿到了 \(8\) 分的好成绩。

正解:

记录两个数组:

最优方案 \(f[]\)

最多最后一次电梯的最大剩余

转移时两个都更新一下就好了。

#include<bits/stdc++.h>
using namespace std;
int n,m,Max_status;
const int N=20,M=(1<<18)+5;
int w[N],res[M],f[M];
// res => 最优方案下留下的最多体积
// f   => 最有方案要的电梯乘坐次数 
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i) scanf("%d",&w[i]);
    Max_status=(1<<n)-1;
    memset(f,0x3f,sizeof(f));
    f[0]=1; res[0]=m;// 一开始已经要做一次电梯 
    for(int s=0;s<=Max_status;++s){
        for(int i=1;i<=n;++i) if(!(s&(1<<(i-1)))){
            // 这次塞下了 
            if(res[s]>=w[i] && f[s|(1<<(i-1))]>=f[s])
                f[s|(1<<(i-1))]=min(f[s|(1<<(i-1))],f[s]),
                res[s|(1<<(i-1))]=max(res[s|(1<<(i-1))],res[s]-w[i]);
            // 这次放不下 
            else if(res[s]<w[i] && f[s|(1<<(i-1))]>=f[s]+1)
                f[s|(1<<(i-1))]=min(f[s|(1<<(i-1))],f[s]+1),
                res[s|(1<<(i-1))]=max(res[s|(1<<(i-1))],m-w[i]);
        }
    }
    printf("%d\n",f[Max_status]);
    return 0;
} 

猜你喜欢

转载自www.cnblogs.com/JCNL666/p/10739041.html