当前位置:首页 » 操作系统 » 背包算法java

背包算法java

发布时间: 2022-09-05 18:40:43

1. 背包问题的算法

1)登上算法
用登山算法求解背包问题 function []=DengShan(n,G,P,W) %n是背包的个数,G是背包的总容量,P是价值向量,W是物体的重量向量 %n=3;G=20;P=[25,24,15];W2=[18,15,10];%输入量 W2=W; [Y,I]=sort(-P./W2);W1=[];X=[];X1=[]; for i=1:length(I) W1(i)=W2(I(i)); end W=W1; for i=1:n X(i)=0; RES=G;%背包的剩余容量 j=1; while W(j)<=RES X(j)=1; RES=RES-W(j); j=j+1; end X(j)=RES/W(j); end for i=1:length(I) X1(I(i))=X(i); end X=X1; disp('装包的方法是');disp(X);disp(X.*W2);disp('总的价值是:');disp(P*X');

时间复杂度是非指数的

2)递归法
先看完全背包问题
一个旅行者有一个最多能用m公斤的背包,现在有n种物品,每件的重量分别是W1,W2,...,Wn,
每件的价值分别为C1,C2,...,Cn.若的每种物品的件数足够多.
求旅行者能获得的最大总价值。
本问题的数学模型如下:
设 f(x)表示重量不超过x公斤的最大价值,
则 f(x)=max{f(x-i)+c[i]} 当x>=w[i] 1<=i<=n
可使用递归法解决问题程序如下:
program knapsack04;
const maxm=200;maxn=30;
type ar=array[0..maxn] of integer;
var m,n,j,i,t:integer;
c,w:ar;
function f(x:integer):integer;
var i,t,m:integer;
begin
if x=0 then f:=0 else
begin
t:=-1;
for i:=1 to n do
begin
if x>=w[i] then m:=f(x-i)+c[i];
if m>t then t:=m;
end;
f:=t;
end;
end;
begin
readln(m,n);
for i:= 1 to n do
readln(w[i],c[i]);
writeln(f(m));
end.
说明:当m不大时,编程很简单,但当m较大时,容易超时.
4.2 改进的递归法
改进的的递归法的思想还是以空间换时间,这只要将递归函数计算过程中的各个子函数的值保存起来,开辟一个
一维数组即可
程序如下:
program knapsack04;
const maxm=2000;maxn=30;
type ar=array[0..maxn] of integer;
var m,n,j,i,t:integer;
c,w:ar;
p:array[0..maxm] of integer;
function f(x:integer):integer;
var i,t,m:integer;
begin
if p[x]<>-1 then f:=p[x]
else
begin
if x=0 then p[x]:=0 else
begin
t:=-1;
for i:=1 to n do
begin
if x>=w[i] then m:=f(i-w[i])+c[i];
if m>t then t:=m;
end;
p[x]:=t;
end;
f:=p[x];
end;
end;
begin
readln(m,n);
for i:= 1 to n do
readln(w[i],c[i]);
fillchar(p,sizeof(p),-1);
writeln(f(m));
end.
3)贪婪算法
改进的背包问题:给定一个超递增序列和一个背包的容量,然后在超递增序列中选(只能选一次)或不选每一个数值,使得选中的数值的和正好等于背包的容量。

代码思路:从最大的元素开始遍历超递增序列中的每个元素,若背包还有大于或等于当前元素值的空间,则放入,然后继续判断下一个元素;若背包剩余空间小于当前元素值,则判断下一个元素
简单模拟如下:

#define K 10
#define N 10

#i nclude <stdlib.h>
#i nclude <conio.h>

void create(long array[],int n,int k)
{/*产生超递增序列*/
int i,j;
array[0]=1;
for(i=1;i<n;i++)
{
long t=0;
for(j=0;j<i;j++)
t=t+array[j];
array[i]=t+random(k)+1;
}
}
void output(long array[],int n)
{/*输出当前的超递增序列*/
int i;
for(i=0;i<n;i++)
{
if(i%5==0)
printf("\n");
printf("%14ld",array[i]);
}
}

void beibao(long array[],int cankao[],long value,int count)
{/*背包问题求解*/
int i;
long r=value;
for(i=count-1;i>=0;i--)/*遍历超递增序列中的每个元素*/
{
if(r>=array[i])/*如果当前元素还可以放入背包,即背包剩余空间还大于当前元素*/
{
r=r-array[i];
cankao[i]=1;
}
else/*背包剩余空间小于当前元素值*/
cankao[i]=0;
}
}

void main()
{
long array[N];
int cankao[N]={0};
int i;
long value,value1=0;
clrscr();
create(array,N,K);
output(array,N);
printf("\nInput the value of beibao:\n");
scanf("%ld",&value);
beibao(array,cankao,value,N);
for(i=0;i<N;i++)/*所有已经选中的元素之和*/
if(cankao[i]==1)
value1+=array[i];
if(value==value1)
{
printf("\nWe have got a solution,that is:\n");
for(i=0;i<N;i++)
if(cankao[i]==1)
{
if(i%5==0)
printf("\n");
printf("%13ld",array[i]);
}
}
else
printf("\nSorry.We have not got a solution.\n");
}
贪婪算法的另一种写法,beibao函数是以前的代码,用来比较两种算法:

#define K 10
#define N 10

#i nclude <stdlib.h>
#i nclude <conio.h>

void create(long array[],int n,int k)
{
int i,j;
array[0]=1;
for(i=1;i<n;i++)
{
long t=0;
for(j=0;j<i;j++)
t=t+array[j];
array[i]=t+random(k)+1;
}
}
void output(long array[],int n)
{
int i;
for(i=0;i<n;i++)
{
if(i%5==0)
printf("\n");
printf("%14ld",array[i]);
}
}

void beibao(long array[],int cankao[],long value,int count)
{
int i;
long r=value;
for(i=count-1;i>=0;i--)
{
if(r>=array[i])
{
r=r-array[i];
cankao[i]=1;
}
else
cankao[i]=0;
}
}

int beibao1(long array[],int cankao[],long value,int n)
{/*贪婪算法*/
int i;
long value1=0;
for(i=n-1;i>=0;i--)/*先放大的物体,再考虑小的物体*/
if((value1+array[i])<=value)/*如果当前物体可以放入*/
{
cankao[i]=1;/*1表示放入*/
value1+=array[i];/*背包剩余容量减少*/
}
else
cankao[i]=0;
if(value1==value)
return 1;
return 0;
}

void main()
{
long array[N];
int cankao[N]={0};
int cankao1[N]={0};
int i;
long value,value1=0;
clrscr();
create(array,N,K);
output(array,N);
printf("\nInput the value of beibao:\n");
scanf("%ld",&value);
beibao(array,cankao,value,N);
for(i=0;i<N;i++)
if(cankao[i]==1)
value1+=array[i];
if(value==value1)
{
printf("\nWe have got a solution,that is:\n");
for(i=0;i<N;i++)
if(cankao[i]==1)
{
if(i%5==0)
printf("\n");
printf("%13ld",array[i]);
}
}
else
printf("\nSorry.We have not got a solution.\n");
printf("\nSecond method:\n");
if(beibao1(array,cankao1,value,N)==1)
{
for(i=0;i<N;i++)
if(cankao1[i]==1)
{
if(i%5==0)
printf("\n");
printf("%13ld",array[i]);
}
}
else
printf("\nSorry.We have not got a solution.\n");
}

4)动态规划算法

解决0/1背包问题的方法有多种,最常用的有贪婪法和动态规划法。其中贪婪法无法得到问题的最优解,而动态规划法都可以得到最优解,下面是用动态规划法来解决0/1背包问题。

动态规划算法与分治法类似,其基本思想是将待求解问题分解成若干个子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划法求解的问题,经分解得到的子问题往往不是互相独立的,若用分治法解这类问题,则分解得到的子问题数目太多,以至于最后解决原问题需要耗费过多的时间。动态规划法又和贪婪算法有些一样,在动态规划中,可将一个问题的解决方案视为一系列决策的结果。不同的是,在贪婪算法中,每采用一次贪婪准则便做出一个不可撤回的决策,而在动态规划中,还要考察每个最优决策序列中是否包含一个最优子序列。

0/1背包问题

在0 / 1背包问题中,需对容量为c 的背包进行装载。从n 个物品中选取装入背包的物品,每件物品i 的重量为wi ,价值为pi 。对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高,即p1*x1+p2*x1+...+pi*xi(其1<=i<=n,x取0或1,取1表示选取物品i) 取得最大值。
在该问题中需要决定x1 .. xn的值。假设按i = 1,2,...,n 的次序来确定xi 的值。如果置x1 = 0,则问题转变为相对于其余物品(即物品2,3,.,n),背包容量仍为c 的背包问题。若置x1 = 1,问题就变为关于最大背包容量为c-w1 的问题。现设r?{c,c-w1 } 为剩余的背包容量。
在第一次决策之后,剩下的问题便是考虑背包容量为r 时的决策。不管x1 是0或是1,[x2 ,.,xn ] 必须是第一次决策之后的一个最优方案,如果不是,则会有一个更好的方案[y2,.,yn ],因而[x1,y2,.,yn ]是一个更好的方案。
假设n=3, w=[100,14,10], p=[20,18,15], c= 116。若设x1 = 1,则在本次决策之后,可用的背包容量为r= 116-100=16 。[x2,x3 ]=[0,1] 符合容量限制的条件,所得值为1 5,但因为[x2,x3 ]= [1,0] 同样符合容量条件且所得值为1 8,因此[x2,x3 ] = [ 0,1] 并非最优策略。即x= [ 1,0,1] 可改进为x= [ 1,1,0 ]。若设x1 = 0,则对于剩下的两种物品而言,容量限制条件为116。总之,如果子问题的结果[x2,x3 ]不是剩余情况下的一个最优解,则[x1,x2,x3 ]也不会是总体的最优解。在此问题中,最优决策序列由最优决策子序列组成。假设f (i,y) 表示剩余容量为y,剩余物品为i,i + 1,...,n 时的最优解的值,即:利用最优序列由最优子序列构成的结论,可得到f 的递归式为:
当j>=wi时: f(i,j)=max{f(i+1,j),f(i+1,j-wi)+vi} ①式
当0<=j<wi时:f(i,j)=f(i+1,j) ②式
fn( 1 ,c) 是初始时背包问题的最优解。
以本题为例:若0≤y<1 0,则f ( 3 ,y) = 0;若y≥1 0,f ( 3 ,y) = 1 5。利用②式,可得f (2, y) = 0 ( 0≤y<10 );f(2,y)= 1 5(1 0≤y<1 4);f(2,y)= 1 8(1 4≤y<2 4)和f(2,y)= 3 3(y≥2 4)。因此最优解f ( 1 , 11 6 ) = m a x {f(2,11 6),f(2,11 6 - w1)+ p1} = m a x {f(2,11 6),f(2,1 6)+ 2 0 } = m a x { 3 3,3 8 } = 3 8。
现在计算xi 值,步骤如下:若f ( 1 ,c) =f ( 2 ,c),则x1 = 0,否则x1 = 1。接下来需从剩余容量c-w1中寻求最优解,用f (2, c-w1) 表示最优解。依此类推,可得到所有的xi (i= 1.n) 值。
在该例中,可得出f ( 2 , 116 ) = 3 3≠f ( 1 , 11 6 ),所以x1 = 1。接着利用返回值3 8 -p1=18 计算x2 及x3,此时r = 11 6 -w1 = 1 6,又由f ( 2 , 1 6 ) = 1 8,得f ( 3 , 1 6 ) = 1 4≠f ( 2 , 1 6 ),因此x2 = 1,此时r= 1 6 -w2 = 2,所以f (3,2) =0,即得x3 = 0。

2. java算法背包溢出最小值

java算法背包溢出最小值最小值-1,即最小值+(-1),即1-0000加1-1111,变成0-1111。

最大值+1,即0-1111加0-0001,变成1-0000,即最小值最小值-1,即最小值+(-1),即1-0000加1-1111,变成0-1111,即最大值正数区间和负数区间形成了循环,正数区间最大值+1,就进入了负数区间,负数区间最大值+1,就进入了正数区间。

基本信息

数据结构与算法课程是电子科技大学于2018年02月26日首次在中国大学MOOC开设的慕课课程、国家精品在线开放课程。该课程授课教师为林劼、戴波、刘震、周益民。据2021年3月中国大学MOOC官网显示,该课程已开课7次。

数据结构与算法课程共6个模块,包括绪论、线性表、查找、排序、递归与分治、树与二叉树、图论与贪心算法、动态规划等内容。

数据结构与算法课程是计算机科学与技术的学科基础课程,也是是计算机图形学、计算机网络、编译原理、计算机操作系统等后续课程的基础理论之一,其应用范围也早已扩展到图像处理与模式识别、海量数据挖掘、科学数据处理、复杂网络分析等许多计算机前沿领域。

3. java语言,背包问题,从Excel表中读取数据

基本概念
问题雏形
01背包题目的雏形是:
有N件物品和一个容量为V的背包。第i件物品的体积是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
从这个题目中可以看出,01背包的特点就是:每种物品仅有一件,可以选择放或不放。
其状态转移方程是:
f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
对于这方方程其实并不难理解,方程之中,现在需要放置的是第i件物品,这件物品的体积是c[i],价值是w[i],因此f[i-1][v]代表的就是不将这件物品放入背包,而f[i-1][v-c[i]]+w[i]则是代表将第i件放入背包之后的总价值,比较两者的价值,得出最大的价值存入现在的背包之中。
理解了这个方程后,将方程代入实际题目的应用之中,可得
for (i = 1; i <= n; i++)
for (j = v; j >= c[i]; j--)//在这里,背包放入物品后,容量不断的减少,直到再也放不进了
f[i][j] = max(f[i - 1][j], f[i - 1][j - c[i]] + w[i]);

问题描述
求出获得最大价值的方案。
注意:在本题中,所有的体积值均为整数。
算法分析
对于背包问题,通常的处理方法是搜索。
用递归来完成搜索,算法设计如下:
int make(int i, int j)//处理到第i件物品,剩余的空间为j 初始时i=m , j=背包总容量
{
if (i == 0) return 0;
if (j >= c[i])//(背包剩余空间可以放下物品 i )
{
int r1 = make(i - 1, j - w[i]);//第i件物品放入所能得到的价值
int r2 = make(i - 1, j);//第i件物品不放所能得到的价值
return min(r1, r2);
}
return make(i - 1, j);//放不下物品 i
}
这个算法的时间复杂度是O(n^2),我们可以做一些简单的优化。
由于本题中的所有物品的体积均为整数,经过几次的选择后背包的剩余空间可能会相等,在搜索中会重复计算这些结点,所以,如果我们把搜索过程中计算过的结点的值记录下来,以保证不重复计算的话,速度就会提高很多。这是简单的“以空间换时间”。
我们发现,由于这些计算过程中会出现重叠的结点,符合动态规划中子问题重叠的性质。
同时,可以看出如果通过第N次选择得到的是一个最优解的话,那么第N-1次选择的结果一定也是一个最优解。这符合动态规划中最优子问题的性质。
解决方案
考虑用动态规划的方法来解决,这里的:
阶段:在前N件物品中,选取若干件物品放入背包中
状态:在前N件物品中,选取若干件物品放入所剩空间为W的背包中的所能获得的最大价值
决策:第N件物品放或者不放
由此可以写出动态转移方程:
我们用f[i][j]表示在前 i 件物品中选择若干件放在已用空间为 j 的背包里所能获得的最大价值
f[i][j] = max(f[i - 1][j - W[i]] + P[i], f[i - 1][j]);//j >= W[ i ]
这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要将它详细解释一下:“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[v];如果放第i件物品,那么问题就转化为“前i-1件物品放入已用的容量为c的背包中”,此时能获得的最大价值就是f[c]再加上通过放入第i件物品获得的价值w。
这样,我们可以自底向上地得出在前M件物品中取出若干件放进背包能获得的最大价值,也就是f[m,w]
算法设计如下:
int main()
{
cin >> n >> v;
for (int i = 1; i <= n; i++)
cin >> c[i];//价值
for (int i = 1; i <= n; i++)
cin >> w[i];//体积
for (int i = 1; i <= n; i++)
f[i][0] = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= v; j++)
if (j >= w[i])//背包容量够大
f[i][j] = max(f[i - 1][j - w[i]] + c[i], f[i - 1][j]);
else//背包容量不足
f[i][j] = f[i - 1][j];
cout << f[n][v] << endl;
return 0;
}

由于是用了一个二重循环,这个算法的时间复杂度是O(n*w)。而用搜索的时候,当出现最坏的情况,也就是所有的结点都没有重叠,那么它的时间复杂度是O(2^n)。看上去前者要快很多。但是,可以发现在搜索中计算过的结点在动态规划中也全都要计算,而且这里算得更多(有一些在最后没有派上用场的结点我们也必须计算),在这一点上好像是矛盾的。

4. JAVA背包问题,对于我十万火急!!!!!!求救!!!!求救!!!!

public class Beibao {

/**
* @param args
*/
static int lenth = 5;
static int T = 10;
static int w[]= {2,4,6,8,10};
static int already = 0;
static int a[]= {0,0,0,0,0};
public static void go(int i)
{
if(already == T)
{
for(int j = 0;j< lenth;j++)
{
System.out.print(a[j]+" ");
}
System.out.println();
}
else
{
for(int m = i;m < lenth;m++)
{
if(a[m] == 0 && already + w[m] <= T)
{
a[m] = 1;
already += w[m];
go(m+1);
a[m] = 0;
already -= w[m];
}
}
}
}
public static void main(String[] args)
{
// TODO Auto-generated method stub
go(0);
}

}

5. 0-1背包问题java代码

importjava.io.BufferedInputStream;
importjava.util.Scanner;

publicclasstest{
publicstaticint[]weight=newint[101];
publicstaticint[]value=newint[101];

publicstaticvoidmain(String[]args){
Scannercin=newScanner(newBufferedInputStream(System.in));
intn=cin.nextInt();
intW=cin.nextInt();
for(inti=0;i<n;++i){
weight[i]=cin.nextInt();
value[i]=cin.nextInt();
}
cin.close();
System.out.println(solve(0,W,n));//普通递归
System.out.println("=========");
System.out.println(solve2(weight,value,W));//动态规划表
}

publicstaticintsolve(inti,intW,intn){
intres;
if(i==n){
res=0;
}elseif(W<weight[i]){
res=solve(i+1,W,n);
}else{
res=Math.max(solve(i+1,W,n),solve(i+1,W-weight[i],n)+value[i]);
}
returnres;
}

publicstaticintsolve2(int[]weight,int[]value,intW){
int[][]dp=newint[weight.length+1][W+1];
for(inti=weight.length-1;i>=0;--i){
for(intj=W;j>=0;--j){
dp[i][j]=dp[i+1][j];//从右下往左上,i+1就是刚刚记忆过的背包装到i+1重量时的最大价值
if(j+weight[i]<=W){//dp[i][j]就是背包已经装了j的重量时,能够获得的最大价值
dp[i][j]=Math.max(dp[i][j],value[i]+dp[i+1][j+weight[i]]);
//当背包重量为j时,要么沿用刚刚装的,本次不装,最大价值dp[i][j],要么就把这个重物装了,那么此时背包装的重量为j+weight[i],
//用本次的价值value[i]加上背包已经装了j+weight[i]时还能获得的最大价值,因为是从底下往上,刚刚上一步算过,可以直接用dp[i+1][j+weight[i]]。
//然后选取本次不装weight[i]重物时获得的最大价值以及本次装weight[i]重物获得的最大价值两者之间的最大值
}
}
}
returndp[0][0];
}
}

6. 01背包问题变种:从给定的N个正数中选取若干个数之和最接近M的JAVA写法

BIAS0:= (C-MA(C,2))/MA(C,2)*100;
BIAS1 := (C-MA(C,12))/MA(C,12)*100;
BIAS2 := (C-MA(C,26))/MA(C,26)*100;
BIAS3 := (C-MA(C,48))/MA(C,48)*100;
HXL:=V/CAPITAL*100;
D1:=INDEXC;
D2:=MA(D1,56);
DR2:=D1/D2<0.94;
E1:=(C-HHV(C,12))/HHV(C,12)*10;
E2:=(C-REF(C,26))/REF(C,26)*10;

7. 背包问题算法java实现

任何语言都是一样的,贪心算法,先按价值除重量排序,一个一个的加到背包里,当超过背包允许的重量后,去掉最后加进去一个,跳过这一个以后再加后面的,如果还是超重,再跳过这个,一直到价值最大化位置。

8. 回溯法解决0-1背包问题 java写的 求大神指点~~~~(>_<)~~~~

因为你把n和c 定义为static ,而且初始化为0,。数组也为静态的,一个类中静态的变量在这个类加载的时候就会执行,所以当你这类加载的时候,你的数组static int[] v = new int[n];
static int[] w = new int[n];
就已经初始化完毕,而且数组大小为0。在main方法里动态改变n的值是改变不了已经初始化完毕的数组的大小的,因为组已经加载完毕。

我建议你可以在定义n,c是就为其赋初值。比如(static int n=2 static int c=3)

9. 关于这个java语言描述的0-1背包问题是否有错误

有点问题:
public static void knapsack(int[]v,int[]w,int c,int[][]m)
{
int n=v.length-1;
int jMax=Math.min(w[n]-1,c);
for(int j=0;j<=jMax;j++)
m[n][j]=0;
for(int j=w[n];j<=c;j++)
m[n][j]=v[n];
for(int i=n-1;i>1;i--)
{
jMax=Math.min(w[i]-1,c);
for(int j=0;j<=jMax;j++)
m[i][j]=m[i+1][j];
for(int j=w[i];j<=c;j++)
m[i][j]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);
}
m[1][c]=m[2][c];
if(c>=w[1])
m[1][c]=Math.max(m[1][c],m[2][c-w[1]]+v[1]);
}
public static void traceback(int[][]m,int[]w,int c,int[]x)
{
int n=w.length-1;
for(int i=1;i<n;i++) {
if(m[i][c]==m[i+1][c])x[i]=0;
else {
x[i]=1;
c-=w[i];
}
x[n]=(m[n][c]>0)?1:0;
}

//int n=w.length-1;
for(int i=1;i<n;i++)
if(m[i][c]==m[i+1][c])x[i]=0;
else {
x[i]=1;
c-=w[i];
}
x[n]=(m[n][c]>0)?1:0;
}

热点内容
安卓畅享8a怎么拿出手机卡 发布:2024-05-10 08:18:25 浏览:185
怎么搭建局域网数据库服务器配置 发布:2024-05-10 08:17:29 浏览:656
安卓系统手机怎么解锁 发布:2024-05-10 08:17:27 浏览:472
php数组循环输出 发布:2024-05-10 08:17:18 浏览:677
安卓手机助手导通讯录哪个好 发布:2024-05-10 08:15:49 浏览:281
安卓微信在哪里设置 发布:2024-05-10 08:14:22 浏览:212
苹果抖音如何找回安卓上传的视频 发布:2024-05-10 08:13:42 浏览:437
php学法网 发布:2024-05-10 07:56:10 浏览:210
云服务器十大品牌排行 发布:2024-05-10 07:42:41 浏览:546
stc单片机编程器 发布:2024-05-10 07:34:05 浏览:785