【Luogu】P3052摩天大楼里的奶牛(状压DP)

  参见ZHT467的题解。

  f[i]表示在i这个集合下的最少分组数和当前组最少的容量。

  从1到(1<<n)-1枚举i,对于每个i枚举它的子奶牛,然后重载运算符计算。

  代码如下

  

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<algorithm>
using namespace std;

inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

long long w[100];
int Max;
struct Node{
    long long cnt,v;
}f[270003];
int n,W;
inline Node operator +(const Node a,const int b){
    return a.v+b<=W?(Node){a.cnt,a.v+b}:(Node){a.cnt+1,b};
}

inline bool operator <(const Node a,const Node b){
    if(a.cnt!=b.cnt)    return a.cnt<b.cnt;
    return a.v<b.v;
}

inline Node min(Node a,Node b){    return a<b?a:b;    }


int main(){
    n=read(),W=read();
    Max=(1<<n)-1;
    for(int i=1;i<=n;++i)    w[i]=read();
    for(int i=1;i<=Max;++i){
        f[i]=(Node){200000,W};
        for(int j=1;j<=n;++j){
            if(((1<<(j-1))&i)==0)    continue;
            f[i] = min(f[i],f[(1<<(j-1))^i]+w[j]);
        }
    }
    printf("%lld",f[Max].cnt+1);
    return 0;
}
原文地址:https://www.cnblogs.com/cellular-automaton/p/7561095.html