【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; }