题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2621
题目大意:
题解:
状压dp(然而有背包的思想啊
f[i]表示运了哪些牛最少的往返次数
g[i]表示运了哪些牛后当前电梯剩下的位置..额载重量
那么每次加一只牛,如果位置够的话,就能装进当前的电梯;或者选择开个新电梯来运。
(取往返次数少的
最后要判断一下新电梯有没有装过牛,如果没有装过就不能算上它的次数
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> using namespace std; #define maxn 300000 #define inf 0x7fffffff int f[maxn],g[maxn],w[20]; int mymax(int x,int y){return (x>y)?x:y;} int mymin(int x,int y){return (x<y)?x:y;} int main() { //freopen("skyscraper.in","r",stdin); //freopen("skyscraper.out","w",stdout); int n,c,i,j,mx; scanf("%d%d",&n,&c); for (i=1;i<=n;i++) scanf("%d",&w[i]); mx=(1<<n)-1; for (i=0;i<=mx;i++) f[i]=inf,g[i]=c; f[0]=0; for (i=0;i<mx;i++) { for (j=1;j<=n;j++) if (!(i&(1<<j-1))) { int gp,fp; if (g[i]>=w[j])//看下装不装得进 { gp=g[i]-w[j]; fp=f[i]; }else gp=c-w[j],fp=f[i]+1; if (fp<f[i|(1<<j-1)]) {f[i|(1<<j-1)]=fp;g[i|(1<<j-1)]=gp;} else if (fp==f[i|(1<<j-1)]) g[i|(1<<j-1)]=mymax(g[i|(1<<j-1)],gp); } }if (g[mx]!=c) f[mx]++; printf("%d ",f[mx]); return 0; }