问题描述:
有n头奶牛需要乘电梯上楼,第i 头奶牛重Wi,电梯的载重上限是C,请问电梯最少往返几次才能运完所有的奶牛?
输入格式:
第1行两个整数n(1n18)头牛,C(1C108)电梯的载重上限。
第2..n+1行:第i+1行一个整数Wi(1Wi108)。
输出格式:
一行一个整数,表示电梯的最少往返次数。
输入输出样例:
skyscraper.in
4 10
5
6
3
7
skyscraper.out
3
输入输出解释:
5和3一组,6单独一组,7单独一组。
算法: 状态动规
代码:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=(1<<20)-1;
int f[maxn],s[maxn];
int w[25];
int n,c,Num,i,j,k;
int main()
{
freopen("skyscraper.in","r",stdin);
freopen("skyscraper.out","w",stdout);
scanf("%d%d",&n,&c);
for (i=1;i<=n;i++) scanf("%d",&w[i]);
int Now=(1<<n)-1;
for (i=0;i<=Now;i++)
{
f[i]=n;
s[i]=c;
}
f[0]=0;
for (i=0;i<Now;i++)
for (j=1;j<=n;j++)
if (!(i&(1<<j-1)))
{
int sl,ps;
if (s[i]>=w[j])
{
sl=s[i]-w[j];
ps=f[i];
}
else
{
sl=c-w[j];
ps=f[i]+1;
}
if (ps<f[i|(1<<j-1)])
{
f[i|(1<<j-1)]=ps;
s[i|(1<<j-1)]=sl;
}
else
if (ps==f[i|(1<<j-1)])
s[i|(1<<j-1)]=max(s[i|(1<<j-1)],sl);
}
if (s[Now]!=c) f[Now]++;
printf("%d\n",f[Now]);
return 0;
}