---to be continued--
=========-2014-12-11=================================================
首先复习一下可分割背包
n种货物
w1,w2,w3,...,wn 【重】
v1, v2,v3,..., vn 【价值】
背包容量C,要求尽可能装下更大价值的货物,其中每种货物都可以选择只装一部分(整数)或者不装。
贪心解法:根据n种货物的价值密度排序,从价值密度最大的开始,尽量装入更多的货物(贪心性质)。
可以证明,上面的贪心策略的局部最优解最后可以使全局解达到最优。
============================================================
现在看看xoj1062 题目描述就不重复了。题目描述:XOJ1062
由于要求获得尽可能少的纸币,从面值最大的开始,尽量拿更多的纸币去找钱。
一些算法细节,
1、5角、1角的面值将导致存在浮点数,原则上不喜欢用浮点,因此可以把所有面值乘以10。
2、找钱的模拟过程尽量简化。
由于每一种面值找钱的过程都类似:先看钱数*面值数有没有大于目前剩下要找的钱数,如果大于==>只取一部分来找钱,如果小于==>全部取了
可以用数组存每一个面值,只需要一次遍历数组就可以了。
【不要去一个一个判断,100块的写一段代码,50块的也写一段类似的代码==>效率极低,并且容易出错;
后面有一题(类似的模拟过程尽可能最简最好)】
算法伪代码:
i = 1..n //遍历一遍所有面值即可
if v[i] * k[i] > C
K+= (int)C/v[i] //找回去的纸币数目
C = C - ( (int)C / v[i] )* v[i]
else
K+= k[i]
C = C - k[i]* v[i]
完整的代码如下:(xoj1062,是不是特别简单?!)
#include <stdio.h>
int v[6] = {500, 100, 50, 10, 5, 1};
int k[6];
int main()
{
int N,C,K=0;
scanf("%d",&N);
for(int i = 0 ; i < 6; i++)
scanf("%d",&k[i]);
C=1000 - 25*N;
for(int i = 0 ; i < 6; i++)
{
if(v[i] * k[i] > C)
{
K+=C/v[i];
C-=( C/v[i] )* v[i];
}
else
{
K+=k[i];
C-=v[i] * k[i];
}
}
if(C == 0)
printf("%d",K);
else
printf("-1");
return 0;
}
现在来看一下poj1017
题目描述poj1017
这个问题解法是“模拟”,模拟一个装箱过程。
物品 -->(放入) 箱子【使箱子数尽量少】
要使总箱子数目最少-->令装箱后的空位置最小-->放入更大的物品为优先,然后统计其剩余空间,让小的物品填充进去-->最后再有剩下的小物品,就再开辟新的箱子来装。
(上面这段描述有些混乱,以后会更新)
因此,将物品按照大小分为2类,一类是直接装入箱子,一类是用来填充箱子的缝隙。
考虑箱子数目与各个种类物品的关系:
1*1,2*2,3*3,4*4,5*5,6*6大小的物品数目分别如下:
a , b , c , d , e , f
设n为箱子的数目,那么:
首先,n += d+e+f, and 若干缝隙:5d个2*2大小缝隙+11e个1*1大小缝隙
其次,查看c的数目是否为4的倍数。
if(c % 4)
n+=c / 4 + 1;
switch(c%4)
case 1: 5个2*2大小缝隙+7个1*1大小缝隙
case 2: 3个2*2大小缝隙+6个1*1大小缝隙
case 3: 1个2*2大小缝隙+5个1*1大小缝隙
else
n += c / 4
再次,就是将1*1和2*2的物品放入上面装箱的空隙中,假如还有剩下物品,再根据剩下的数目另外装箱。
现在发现,可以用两个变量(x和y分别记录)来记录刚刚在前2步中产生的1*1和2*2的空隙数,
x 1*1箱子空隙数
y 2*2箱子空隙数
先把2*2的物品放入空隙中,b - y
b - y > 0 说明2*2物品有剩:
b -= y;
n += b % 9 == 0 ?b / 9:(b / 9 +1,x += (9 - b % 9)*4);
y = 0;
b - y = 0 说明刚好
b - y < 0 说明物品填充不完这类空隙,那就需要1*1的物品来继续填充; x+=( 0 - (b-y) ) * 4
然后就是把1*1的物品放入缝隙了;
与上面的过程类似,这里就不在赘述了。代码如下:
#include<stdio.h>
intmain(){
int a,b,c,d,e,f,x,y;//
while(1){
int n = 0;
x = y = 0;
scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f);
if(a==0&&b==0&&c==0&&d==0&&e==0&&f==0){
break;
}
n += d + e + f;
x += 11 * e;
y += 5 * d;
if(c % 4){
n +=( c / 4 )+ 1;
switch (c % 4)
{
case 1:
x += 7;
y += 5;
break;
case 2:
x += 6;
y += 3;
break;
case 3:
x += 5;
y += 1;
break;
}
}
else
n += c / 4;
a -= x,b -= y;
x = y = 0;
if(b > 0){
if(b % 9){
n += b/9 + 1;
x += (9 - b % 9)*4;
}
else
n += b / 9;
}
else if(b != 0){
b = 0-b;
x += b*4;
}
a -= x;
x = 0;
if(a > 0){
if(a % 36){
n+=a/36 + 1;
x+=(36 - a % 36);
}
else
n+=a/36;
}
else if(a != 0){
a = 0 - a;
x += a;
}
printf("%d\n",n);
}
return 0;
}