當前位置:首頁 » 操作系統 » 背包演算法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;
}

熱點內容
phpcgi啟動 發布:2024-05-20 22:38:57 瀏覽:578
嵌入式存儲伺服器 發布:2024-05-20 22:14:55 瀏覽:395
sql分組條件 發布:2024-05-20 22:08:49 瀏覽:16
配網web伺服器一個IP地址 發布:2024-05-20 22:07:16 瀏覽:725
電腦板伺服器地址175 發布:2024-05-20 22:03:30 瀏覽:959
編譯靜態函數時 發布:2024-05-20 21:51:20 瀏覽:351
如何在別人的伺服器加模組 發布:2024-05-20 21:28:29 瀏覽:61
伺服器的bios晶元電腦店有嗎 發布:2024-05-20 21:28:26 瀏覽:224
剪輯電影什麼配置 發布:2024-05-20 21:25:17 瀏覽:818
解壓神器中的詭異事件 發布:2024-05-20 21:17:59 瀏覽:7