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

Python015

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 50

float 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(

背包问题小结- []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求和十效率降低。不过这确实是一种很新颖的算法。