免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版
打開APP
未登錄
開通VIP,暢享免費(fèi)電子書等14項超值服
開通VIP
首頁
好書
留言交流
下載APP
聯(lián)系客服
算法設(shè)計與分析 3.9 0-1背包問題
shaobin0604@163.com
>《算法》
2006.09.02
關(guān)注
/**********************************************************
* 3.9 0-1背包問題
*
* 問題描述:
* 給定n種物品和一背包。物品 i 的重量是 w[i] ,其價值為
* v[i] ,背包的容量為 c 。問:應(yīng)該如何選擇裝入背包中的物品,
* 使得裝入背包中物品的總價值最大?
*
* 在選擇裝入背包中的物品時,對每種物品 i 只有兩種選擇,
* 即裝入或不裝入背包。不能將物品 i 裝入背包多次,也不能只
* 裝入部分的物品 i 。因此,該問題稱為 0-1 背包問題。
*
* 此問題的形式化描述為,給定 c > 0, w[i] > 0, v[i] > 0
* 1 <= i <= n ,要求找出 n 元 0-1 向量 x[1 .. n], 其中x[i]
* 等于0或1,使得對 w[i] * x[i] 求和小于等于 c ,并且 v[i] *
* x[i]達(dá)到最大。因此,0-1背包問題是一個特殊的整數(shù)規(guī)劃問題。
*
***********************************************************/
public
class
BagZeroOne
{
/**********************************************************************
* 動態(tài)規(guī)劃解 (Dynamic Programming)
*
*
@param
v in the 物品價值數(shù)組
*
@param
w in the 物品重量數(shù)組
*
@param
c in the 背包的容量
*
@param
m out the 最優(yōu)值數(shù)組,m[i][j]即背包容量為j,可選物品為 i, i + 1, ... , n 時0-1背包問題的最優(yōu)值
*
* 由于0-1背包問題的最優(yōu)子結(jié)構(gòu)性質(zhì),可以建立計算m[i][j]的遞歸式如下:
* / max{m[i + 1][j]), m[i + 1][j - w[i]] + v[i]} j >= w[i]
* m[i][j] /
* \
* \ m[i + 1][j] 0 <= j < w[i]
*
* / v[n] j >= w[n]
* m[n][j] /
* \
* \ 0 0 <= j < w[n]
*
**********************************************************************/
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
>
0
;
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]);
}
*/
}
/**
*
@param
m in the 最優(yōu)值數(shù)組
*
@param
w in the 重量數(shù)組
*
@param
c in the 背包容量
*
@param
x out the 物品選擇數(shù)組 if x[i] == 1 則選物品 i, 否則不選
**/
public
static
void
trackback
(
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
;
//不選物品 i
}
else
{
x
[
i
]
=
1
;
//選擇物品 i
c
-=
w
[
i
]
;
//剩余容量
}
}
x
[
n
]
=
(
m
[
n
][
c
]
>
0
)
?
1
:
0
;
}
public
static
void
testDynamicProgramming
()
{
System
.
out
.
print
(
"
1. --- testDynamicProgramming --->
"
)
;
//輸入
int
c
=
7
;
int
[]
w
=
{
0
,
5
,
3
,
2
,
1
}
;
int
[]
v
=
{
0
,
4
,
4
,
3
,
1
}
;
//應(yīng)該的輸出
int
expectedVMax
=
8
;
int
[]
expectedX
=
{
0
,
0
,
1
,
1
,
1
}
;
//程序運(yùn)行時變量
int
[][]
m
=
new
int
[
w
.
length
][
c
+
1
]
;
int
[]
x
=
new
int
[
w
.
length
]
;
knapsack
(
v
,
w
,
c
,
m
)
;
trackback
(
m
,
w
,
c
,
x
)
;
if
(
m
[
1
][
c
]
==
expectedVMax
&&
java
.
util
.
Arrays
.
equals
(
x
,
expectedX
))
{
System
.
out
.
println
(
"
Test success!
"
)
;
}
else
{
System
.
out
.
println
(
"
Test fail!
"
)
;
}
}
/******************************************************************************
* 暴力解 (Brutal Force)
*
* 物品 i 的重量 w[i], 價值 v[i]
*
* 遞歸算法
* try (物品 i, 當(dāng)前選擇已經(jīng)達(dá)到的重量之和 tw, 本方案可能達(dá)到的總價值 tv)
* {
* //考慮物品 i 包含在當(dāng)前方案的可能性
* if (包含物品 i 是可接受的)
* {
* 將物品 i 包含在當(dāng)前方案中;
* if (i < n - 1)
* try(i + 1, tw + w[i], tv);
* else //又是一個完整方案,因它比前面的方案要好,以它作為最佳方案
* 以當(dāng)前方案作為臨時最佳方案保存
* 恢復(fù)物品 i 不包含在內(nèi)的狀態(tài)
* }
* //考慮物品 i 不包含在當(dāng)前方案中的可能性
* if (不包含物品 i 僅是可考慮的)
* {
* if (i < n - 1)
* try(i + 1, tw, tv - v[i]);
* else //又是一個完整方案,因它比前面的方案要好,以它作為最佳方案
* 以當(dāng)前方案作為臨時最佳方案保存
* }
* }
******************************************************************************/
private
static
int
[]
w
;
//重量
private
static
int
[]
v
;
//價值
private
static
int
[]
x
;
//最優(yōu)解
private
static
int
[]
opt
;
//有效解
private
static
int
c
;
//背包容量
private
static
int
maxv
;
//最優(yōu)值
public
static
void
find
(
int
i
,
int
tw
,
int
tv
)
{
//考慮物品 i 包含在當(dāng)前方案中的可能性
if
(
tw
+
w
[
i
]
<=
c
)
{
//包含物品 i 是可以接受的
opt
[
i
]
=
1
;
if
(
i
<
w
.
length
-
1
)
{
find
(
i
+
1
,
tw
+
w
[
i
]
,
tv
)
;
}
else
{
//又是一個完整方案,因它比前面的方案好,以它作為最佳方案
for
(
int
j
=
0
;
j
<
x
.
length
;
j
++
)
{
x
[
j
]
=
opt
[
j
]
;
}
maxv
=
tv
;
}
opt
[
i
]
=
0
;
}
//考慮物品 i 不包含在當(dāng)前方案中的可能性
if
(
tv
-
v
[
i
]
>
maxv
)
{
//不包含物品 i 是可以考慮的
if
(
i
<
w
.
length
-
1
)
{
find
(
i
+
1
,
tw
,
tv
-
v
[
i
])
;
}
else
{
//又是一個完整方案,因它比前面的方案好,以它作為最佳方案
for
(
int
j
=
0
;
j
<
x
.
length
;
j
++
)
{
x
[
j
]
=
opt
[
j
]
;
}
maxv
=
tv
-
v
[
i
]
;
}
}
}
public
static
void
testBrutalForceRecursive
()
{
System
.
out
.
print
(
"
2. --- testBrutalForceRecursive --->
"
)
;
int
[]
expectedX
=
{
0
,
1
,
1
,
1
}
;
int
expectedMaxV
=
8
;
w
=
new
int
[]
{
5
,
3
,
2
,
1
}
;
v
=
new
int
[]
{
4
,
4
,
3
,
1
}
;
x
=
new
int
[
w
.
length
]
;
opt
=
new
int
[
w
.
length
]
;
c
=
7
;
int
tv
=
0
;
for
(
int
i
:
v
)
{
tv
+=
i
;
}
find
(
0
,
0
,
tv
)
;
// System.out.println("maxv = " + maxv);
// System.out.println("x = " + java.util.Arrays.toString(x));
if
(
maxv
==
expectedMaxV
&&
java
.
util
.
Arrays
.
equals
(
x
,
expectedX
))
{
System
.
out
.
println
(
"
Test success!
"
)
;
}
else
{
System
.
out
.
println
(
"
Test fail!
"
)
;
}
}
/****************************************************************
* 暴力解 (Brutal Force)
*
* 非遞歸算法
*
*
*****************************************************************/
//當(dāng)前候選解中各物品的考慮和選擇狀態(tài),以及置該物品候選解的狀態(tài)
private
static
int
[]
flag
;
//物品的考慮狀態(tài):0.不選;1.將被考慮;2.曾被選中
private
static
int
[]
twe
;
//已經(jīng)達(dá)到的總重量
private
static
int
[]
tve
;
//期望的總價值
private
static
int
maxw
;
//背包容量
private
static
int
[]
cop
;
//臨時最佳解的物品選擇方案,當(dāng)cop[i] 為 1 時,物品 i 在解中
//將考慮物品 i
private
static
void
next
(
int
i
,
int
tw
,
int
tv
)
{
flag
[
i
]
=
1
;
twe
[
i
]
=
tw
;
tve
[
i
]
=
tv
;
}
public
static
int
find
(
int
[]
w
,
int
[]
v
,
int
n
)
{
int
i
,
k
,
f
;
int
maxv
,
tw
,
tv
,
totv
=
0
;
maxv
=
0
;
for
(
int
value
:
v
)
{
totv
+=
value
;
}
next
(
0
,
0
,
totv
)
;
i
=
0
;
while
(
i
>=
0
)
{
f
=
flag
[
i
]
;
tw
=
twe
[
i
]
;
tv
=
tve
[
i
]
;
switch
(
f
)
{
case
0
:
//回退
i
--;
break
;
case
1
:
//考慮被選中
flag
[
i
]
++;
if
(
tw
+
w
[
i
]
<=
maxw
)
{
//選中可行嗎?
if
(
i
<
n
-
1
)
{
next
(
i
+
1
,
tw
+
w
[
i
]
,
tv
)
;
i
++;
}
else
{
maxv
=
tv
;
for
(
k
=
0
;
k
<
n
;
k
++
)
{
cop
[
k
]
=
((
flag
[
k
]
!=
0
)
?
1
:
0
)
;
}
}
}
break
;
default
:
//flag等于2
flag
[
i
]
=
0
;
if
(
tv
-
v
[
i
]
>
maxv
)
{
//不選物品 i 可行嗎?
if
(
i
<
n
-
1
)
{
next
(
i
+
1
,
tw
,
tv
-
v
[
i
])
;
i
++;
}
else
{
maxv
=
tv
-
v
[
i
]
;
for
(
k
=
0
;
k
<
n
;
k
++
)
{
cop
[
k
]
=
((
flag
[
k
]
!=
0
)
?
1
:
0
)
;
}
}
}
break
;
}
}
return
maxv
;
}
public
static
void
testBrutalForceNotRecursive
()
{
System
.
out
.
print
(
"
3. --- testBrutalForceNotRecursive --->
"
)
;
int
[]
expectedX
=
{
0
,
1
,
1
,
1
}
;
int
expectedMaxV
=
8
;
int
[]
w
=
new
int
[]
{
5
,
3
,
2
,
1
}
;
int
[]
v
=
new
int
[]
{
4
,
4
,
3
,
1
}
;
int
n
=
w
.
length
;
cop
=
new
int
[
n
]
;
flag
=
new
int
[
n
]
;
twe
=
new
int
[
n
]
;
tve
=
new
int
[
n
]
;
maxw
=
7
;
int
maxv
=
find
(
w
,
v
,
n
)
;
// System.out.println("maxv = " + maxv);
// System.out.println("x = " + java.util.Arrays.toString(x));
if
(
maxv
==
expectedMaxV
&&
java
.
util
.
Arrays
.
equals
(
cop
,
expectedX
))
{
System
.
out
.
println
(
"
Test success!
"
)
;
}
else
{
System
.
out
.
println
(
"
Test fail!
"
)
;
}
}
public
static
void
main
(
String
[]
args
)
{
testDynamicProgramming
()
;
testBrutalForceRecursive
()
;
testBrutalForceNotRecursive
()
;
}
}
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點(diǎn)擊舉報
。
打開APP,閱讀全文并永久保存
查看更多類似文章
猜你喜歡
類似文章
五大常見算法策略之——動態(tài)規(guī)劃策略(Dynamic Programming)
0-1背包
面試中常見遞歸題目 Java版
Java面試中經(jīng)常問到的算法題 - - JavaEye技術(shù)網(wǎng)站
七大常見排序算法總結(jié)
經(jīng)典算法
更多類似文章 >>
生活服務(wù)
首頁
萬象
文化
人生
生活
健康
教育
職場
理財
娛樂
藝術(shù)
上網(wǎng)
留言交流
回頂部
聯(lián)系我們
分享
收藏
點(diǎn)擊這里,查看已保存的文章
導(dǎo)長圖
關(guān)注
一鍵復(fù)制
下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!
聯(lián)系客服
微信登錄中...
請勿關(guān)閉此頁面
先別劃走!
送你5元優(yōu)惠券,購買VIP限時立減!
5
元
優(yōu)惠券
優(yōu)惠券還有
10:00
過期
馬上使用
×