C语言 贪心算法求背包问题

Python014

C语言 贪心算法求背包问题,第1张

是你的冒泡排序出了问题~你吧 原来的1-2-3号按照东西的价值重新排列现在的1-2-3对应原来的2-1-3了所以 你输出的时候是按 1-2-3输出的话 就等于第一个是原来的X2 第二个是X1第三个是X3而且你的冒泡排序用错了 只比较了 P[0]/K[0]和P[1]/K[1] P[1]/K[1]和P[2]/K[2]周一我去学校帮你重新改改 我家的机器没有C++周一晚上我会上传答案~我最近正好也要做算法的作业~ #include <stdio.h>#include <math.h>#define N 50float find(float p[N],float w[N],float x[N] ,float M,int n) /*先放单位价值量大的物体,再考虑小的物体*/{int i float maxprice for (i = 0i <ni++)x[i] = 0 i = 0 maxprice=0 while (i <n &&w[i] <M){M=M-w[i] x[i] =w[i]/* 表示放入数量 */maxprice=maxprice+p[i] x[n-1]=M i++ }if (i <n &&M>0){maxprice=maxprice+p[i]*x[i]/w[i] i++ }return maxprice}int main(){int n,flag=1 float temp,M,w[N],p[N],x[N]int a[N],b[N] int k,j,l=0 printf(

#include "iostream.h"

#include "stdio.h"

#include <cstdlib>

struct stone

{

int name

int weight//物品的剩余重量

int weight_t//物品的重量

float benefit//物品的价值

//float b

}

//按物品的效益排序

void sort(stone *data,int num)

{

//仅剩一个元素时排序完毕

if(num<1)

return

int low=0,high=num

stone key_s=data[low]//取数组的第一个作为关键字

float key=(float)key_s.benefit/key_s.weight

int empty=low//目标位置初始位置为low指向的位置

while(low<high)

{

if(low==empty)//后面的指针向前走

{

//找到比关键字小的元素把它移到low指向的位置

while((data[high].benefit/data[high].weight<key)&&(high>low))

{

high--

}

if(data[high].benefit/data[high].weight>=key)

{

data[low]=data[high]

empty=high

}

}

else if(high==empty)//前面的指针向后走

{

//找到比关键字大的元素把它移到high指向的位置

while((data[low].benefit/data[low].weight>=key)&&(low<high))

{

low++

}

if(data[low].benefit/data[low].weight<key)

{

data[high]=data[low]

empty=low

}

}

}

data[empty]=key_s//把关键字放到划分完毕后两部分的中间位置

//关键字前面的数列继续递推

if(empty>1)

sort(data,empty-1)

//关键字后面的数列继续递推

if(num-empty-1>0)

sort(data+empty+1,num-empty-1)

}

//输入物品的信息

void inputstone(stone *bag,int num)

{

for(int i=0i<numi++)

{

bag[i].name=i+1//物品的名字

printf("请输入第%d号物品的重量:",i+1)

scanf("%d",&bag[i].weight)

if (bag[i].weight<=0)

{printf("物品的重量必须大于0!\n")}

printf("请输入第%d号物品的价值:",i+1)

scanf("%f",bag[i].benefit)

if (bag[i].benefit<=0)

{printf("物品的价值必须大于0!\n")}

bag[i].weight_t=bag[i].weight

}

}

//主函数

int main(int argc, char* argv[])

{ int i

int num=0//放入物品的数量

int weight=0//背包可容纳的重量

float benefit=0//总效益

stone *bag//物品

/////输入背包可容纳的重量

do

{

printf("请输入背包可容纳的重量:")

scanf("%d",&weight)

if (weight<=0)

printf("背包可容纳的重量必须大于0!\n")

}while(weight<=0)

//输入物品种类

do

{

printf("请输入物品的数量:")

scanf("%d",&num)

if (num<=0)

printf("物品数量必须大于0!\n")

}while(num<=0)

bag=new stone[num]//物品数组

inputstone(bag,num)//输入物品的信息

sort(bag,num-1)//按单位效益排序

for(i=0i<num&&weight>0i++)

{

stone *temp=bag+i

if(weight>=temp->weight)

{

weight-=temp->weight

temp->weight=0

benefit+=temp->benefit

continue

}

else

{

temp->weight-=weight

weight=0

benefit+=(temp->benefit*(1-(float)temp->weight/temp->weight_t))

break

}

}

////////输出结果//////////

printf("物品种类 放入的比例 每单位效益 ")

for(i=0i<numi++)

{

stone *temp=bag+i

printf("%d类物品",temp->name)

printf("\t\t%.2f\t\t",(temp->weight_t-temp->weight)/(float)temp->weight_t)

printf(" %.4f\n",temp->benefit/(float)temp->weight_t)

}

printf("总效益:%.2f",benefit)

delete bag

getchar()

system("PAUSE")

return EXIT_SUCCESS

return 0

}

背包问题小结- []2006-07-28

做到背包问题觉得很有意思,写写看看。

完全背包问题可以用贪心算法。

代码如下:

program bag1

const maxn=10

var

goods:array[1..maxn,1..3] of integer

s:array[1..maxn] of real

i,j:integer

m,n:integer

y:integer

x:real

function max:integer

var m:real

i,j:integer

begin

m:=0

for i:=1 to n do

if (goods[i,3]=0) and (m max:=j

end

procedure choose

var i,j:integer

begin

while y begin

if y begin

i:=max

if m>=y+goods[i,1] then begin goods[i,3]:=1x:=x+goods[i,2]y:=y+goods[i,1]end else

begin

x:=x+(m-y)*s[i]

y:=m

end

end

end

end

begin

fillchar(goods,sizeof(goods),0)

assign(input,'b.txt')

reset(input)

readln(m,n)

for j:=1 to n do

read(goods[j,1])

readln

for j:=1 to n do

read(goods[j,2])

for j:=1 to n do

s[j]:=goods[j,2]/goods[j,1]

close(input)

choose

writeln(x:5:2)

end.

编得不是很好 ^-^ 献丑了。

我来说说0/1背包问题。

状态:当前物品n

算符:j=0(当前物品不放入背包) 或 j=1(当前物品放入背包)

这就很好说了,还是把yes函数一改,问题OK了。

代码如下:

program bag2

const maxn=10

var i:integer

goods:array[1..maxn,1..3] of integer{原始数据}

s:array[1..maxn] of integer{当前的状态}

r:array[1..maxn] of integer{当前的总质量}

m:integer{背包容量}

max:integer{物品个数}

procedure try(n:integer)

var j:integer

{function yes:boolean

var k:integer

t:integer

mn:integer

begin

mn:=0

t:=goods[n,3]

goods[n,3]:=j

for k:=1 to n do

if goods[k,3]=1 then inc(mn,goods[k,1])

goods[n,3]:=t

if mn>m then yes:=false else yes:=true

end}

begin

if n=max+1 then begin if x for i:=1 to max do s[i]:=goods[i,3]{保存最优解}end

end else

begin

if r[n-1]>m then exit{已超过背包总容量}

for j:=1 downto 0 do

begin

if j=1 then r[n]:=r[n-1]+goods[n,1]

if j=0 then r[n]:=r[n]-goods[n,1]

if {yes}r[n]<=m then begin goods[n,3]:=jtry(n+1)goods[n,3]:=0end

end

end

end

begin

assign(input,'b.txt')

reset(input)

readln(m,max)

for i:=1 to max do

read(goods[i,1])

readln

for i:=1 to max do

read(goods[i,2])

close(input)

try(1)

for i:=1 to 7 do

write(s[i]:3)

writeln

writeln(x)

end.

用yes 函数要从头到当前求已装入背包物品的总质量,时间效率不高。所以我们引入r[n]数组来记录当前背包总质量(很好用!)注意用r[n-1]>m来做剪枝,以再次提高时间效率。

DC跟我说可以用二进制解此类问题。我觉得很有创意,也说说。比如8个物品,每个物品有0/1两种状态所以我们从(00000000)(二进制 )到(11111111)(二进制)循环即可。然后在分离十进制数对应起来即可。但在实际的操作中发现效率比回溯还低,我想有两方面的原因:1、显而易见,不可能做剪枝。2、每一次结果都要从1到8求和十效率降低。不过这确实是一种很新颖的算法。