zoj3623
题意:输入一个n和l,n代表n组值,l代表敌人的总权值,再输入n组值,每组两个数,分别代表制造这组战舰需要的时间和每秒钟可以对敌人造成伤害的权值,创建战舰可以重复创建。问需要多长时间,可以打败敌人。
思路:完全背包。
#include <cstdio>
#include <cstring>
#define max(x,y) ((x)>(y)?(x):(y))
const int INF=0x0fffffff;
int f[370],time[30],lenth[370];
int n,L;
void CompletePack ()
{
for (int i=1;i<=n;i++)
for (int j=0;j<330;j++)
f[j+time[i]]=max(f[j+time[i]],f[j]+j*lenth[i]);
}
int main ()
{
int i;
while (~scanf("%d%d",&n,&L))
{
memset(f,0,sizeof(f));
for (i=1;i<=n;i++)
scanf("%d%d",&time[i],&lenth[i]);
CompletePack ();
for (i=1;i<=330;i++)
if (f[i]>=L)
{
printf("%d\n",i);
break;
}
}
return 0;
}
题意:给你一堆石头,石头的价值有1,2,3,4,5,6(N=6)种,其对应的数量也给出,问能否实现平均分配?
思路:先求出总价值sum,如果奇数,显然不能,如果是偶数,多重背包
#include <cstdio>
#include <cstring>
#define max(x,y) (x)>(y)?(x):(y)
#define min(x,y) (x)<(y)?(x):(y)
int n,sum,v;
int f[10000*6+5];
void ZeroOnePack (int cost, int weight)
{
for (int j=v;j>=cost;j--)
f[j] = max(f[j], f[j-cost] + weight);
}
void CompletePack (int cost, int weight)
{
for (int j=cost;j<=v;j++)
f[j] = max(f[j], f[j-cost] + weight);
}
void MultiplePack (int cost, int weight, int all)
{
if (cost*all >= v) //如果足够,转化为完全背包
{
CompletePack (cost, weight);
return ;
}
int k=1;
while (k < all) //否则利用二进制的思想将其划分为若干个小物品
{
ZeroOnePack (k*cost, k*weight);
all-=k;
k<<=1;
}
ZeroOnePack (all*cost,all*weight);
}
int main()
{
int cas=0;
while (true)
{
cas++;
int i;
sum=0;
int sumval=0;
int num[10];
memset(f,0,sizeof(f));
for (i=1;i<=6;i++)
{
scanf("%d",&num[i]);
sum+=num[i];
sumval+=i*num[i];
}
if (sum==0)
break;
if (sumval%2==1)
{
printf("Collection #%d:\nCan't be divided.\n\n",cas);
continue;
}
v=sumval/2;
for (i=1;i<=6;i++)
MultiplePack (i,i,num[i]);
if (f[v]==sumval/2)
printf("Collection #%d:\nCan be divided.\n",cas);
else
printf("Collection #%d:\nCan't be divided.\n",cas);
printf("\n");
}
return 0;
}
Hdu2844
题意:求出硬币的组合方案,使得硬币的总价值不超过价值m
思路:多重背包
#include <cstdio>
#include <cstring>
#define max(x,y) (x)>(y)?(x):(y)
#define min(x,y) (x)<(y)?(x):(y)
const int INF=0x3fffffff;
int n,v;
int f[100005],a[105],c[105];
void ZeroOnePack (int cost, int weight)
{
for (int j=v;j>=cost;j--)
f[j] = max(f[j], f[j-cost] + weight);
}
void CompletePack (int cost, int weight)
{
for (int j=cost;j<=v;j++)
f[j] = max(f[j], f[j-cost] + weight);
}
void MultiplePack (int cost, int weight, int all)
{
if (cost*all >= v) //如果足够,转化为完全背包
{
CompletePack (cost, weight);
return ;
}
int k=1;
while (k < all) //否则利用二进制的思想将其划分为若干个小物品
{
ZeroOnePack (k*cost, k*weight);
all-=k;
k<<=1;
}
ZeroOnePack (all*cost,all*weight);
}
int main()
{
while (scanf("%d%d",&n,&v),n+v)
{
int i,ans=0;
memset(f,0x8f,sizeof(f)); //赋值负无穷
// for (i=1;i<v+5;i++)
// f[i]=-INF;
f[0]=0;
for (i=0;i<n;i++)
scanf("%d",&a[i]);
for (i=0;i<n;i++)
scanf("%d",&c[i]);
for (i=0;i<n;i++)
MultiplePack (a[i],a[i],c[i]);
for (i=1;i<=v;i++)
// if (f[i]>0) 由恰好装满背包的性质这样也可以
if (f[i]==i)
ans++;
printf("%d\n",ans);
}
return 0;
}