Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
qq_36480062
Algorithm
提交
9f2a7a56
A
Algorithm
项目概览
qq_36480062
/
Algorithm
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
Algorithm
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
9f2a7a56
编写于
9月 26, 2020
作者:
qq_36480062
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
c
上级
1717b198
变更
16
隐藏空白更改
内联
并排
Showing
16 changed file
with
186 addition
and
52 deletion
+186
-52
ACWing/src/dp/树形dp/有依赖的背包问题.java
ACWing/src/dp/树形dp/有依赖的背包问题.java
+21
-20
ACWing/src/dp/状态压缩dp/哈密尔顿回路.java
ACWing/src/dp/状态压缩dp/哈密尔顿回路.java
+1
-1
ACWing/src/dp/状态压缩dp/骑士.java
ACWing/src/dp/状态压缩dp/骑士.java
+2
-3
ACWing/src/dp/状态机模型/大盗阿福.java
ACWing/src/dp/状态机模型/大盗阿福.java
+6
-1
ACWing/src/dp/状态机模型/股票买卖4.java
ACWing/src/dp/状态机模型/股票买卖4.java
+6
-2
ACWing/src/dp/背包模型/买书.java
ACWing/src/dp/背包模型/买书.java
+1
-1
ACWing/src/dp/背包模型/分组背包问题.java
ACWing/src/dp/背包模型/分组背包问题.java
+2
-1
ACWing/src/dp/背包模型/多重背包1.java
ACWing/src/dp/背包模型/多重背包1.java
+2
-0
ACWing/src/dp/背包模型/多重背包二进制优化.java
ACWing/src/dp/背包模型/多重背包二进制优化.java
+30
-3
ACWing/src/dp/背包模型/数字组合.java
ACWing/src/dp/背包模型/数字组合.java
+11
-7
ACWing/src/dp/背包模型/普通二维费用背包.java
ACWing/src/dp/背包模型/普通二维费用背包.java
+1
-1
ACWing/src/dp/背包模型/机器分配.java
ACWing/src/dp/背包模型/机器分配.java
+5
-2
ACWing/src/dp/背包模型/混合背包.java
ACWing/src/dp/背包模型/混合背包.java
+3
-2
ACWing/src/dp/背包模型/潜水员二维费用背包.java
ACWing/src/dp/背包模型/潜水员二维费用背包.java
+8
-6
ACWing/src/dp/背包模型/背包问题求具体方案.java
ACWing/src/dp/背包模型/背包问题求具体方案.java
+8
-2
ACWing/src/dp/背包模型/背包问题求方案数量.java
ACWing/src/dp/背包模型/背包问题求方案数量.java
+79
-0
未找到文件。
ACWing/src/dp/树形dp/有依赖的背包问题.java
浏览文件 @
9f2a7a56
...
...
@@ -3,20 +3,7 @@ package dp.树形dp;
import
java.util.Scanner
;
/**
* 有n个物品和容量为V的背包
* 物品之间有依赖关系,关系组成一颗树的形状,
* 如果要选一个物品,则必选他的父节点
* 求最大价值
* dfs+dp dp.树形dp
* 状态定义:集合f[u,j]:所有从以u为根的子树中选,且总体积不超过j的选法
* 属性:max最大价值
* 集合划分:子树1,子树3,子树3
* 再根据体积划分子树:体积是0-m 有m+1总可能
* 用一个数字表示一类方案
* 把每一颗子树看做物品组,分组背包问题
* 链式前向星建图
* 有 N 个物品和一个容量是 V
* 的背包。
* 有 N 个物品和一个容量是 V的背包。
* 物品之间具有依赖关系,且依赖关系组成一棵树的形状。如果选择一个物品,则必须选择它的父节点。
* 如下图所示:
* 如果选择物品5,则必须选择物品1和2。这是因为2是5的父节点,1是2的父节点。
...
...
@@ -49,6 +36,20 @@ import java.util.Scanner;
* 3 6 2
* 输出样例:
* 11
* <p>
* 有n个物品和容量为V的背包
* 物品之间有依赖关系,关系组成一颗树的形状,
* 如果要选一个物品,则必选他的父节点
* 求最大价值
* dfs+dp dp.树形dp
* 状态定义:集合f[u,j]:所有从以u为根的子树中选,且总体积不超过j的选法
* 属性:max最大价值
* 集合划分:子树1,子树3,子树3
* 划分依据:体积为0~m的子树,把每一棵子树看做一个物品做
* 再根据体积划分子树:体积是0-m 有m+1总可能
* 用一个数字表示一类方案
* 把每一颗子树看做物品组,分组背包问题
* 链式前向星建树
*/
public
class
有依赖的背包问题
{
...
...
@@ -62,7 +63,7 @@ public class 有依赖的背包问题 {
w
[
i
]
=
sc
.
nextInt
();
p
=
sc
.
nextInt
();
if
(
p
==
-
1
)
root
=
i
;
else
add
(
p
,
i
);
else
add
(
p
,
i
);
//p向i连一条边,父节点向子节点连边
}
dfs
(
root
);
System
.
out
.
println
(
f
[
root
][
m
]);
...
...
@@ -74,7 +75,7 @@ public class 有依赖的背包问题 {
dfs
(
e
[
i
]);
//以u为根的子树,每一棵子树都是一个分组背包问题
//抽象成2层
for
(
int
j
=
m
-
v
[
u
];
j
>=
0
;
j
--)
{
//枚举体积
for
(
int
j
=
m
-
v
[
u
];
j
>=
0
;
j
--)
{
//枚举体积
,因为根节点必须要选,预留m-v[u
for
(
int
k
=
0
;
k
<=
j
;
k
++)
{
//枚举决策,分为以0~m的一些决策
f
[
u
][
j
]
=
Math
.
max
(
f
[
u
][
j
],
f
[
u
][
j
-
k
]
+
f
[
son
][
k
]);
//以u为根节点,在剩余体积为0~m-v[u]的情况下,选子树
...
...
@@ -95,11 +96,11 @@ public class 有依赖的背包问题 {
static
int
N
=
110
;
static
int
[]
head
=
new
int
[
N
],
e
=
new
int
[
N
],
ne
=
new
int
[
N
];
static
int
n
,
m
,
cnt
=
1
;
static
int
n
,
m
,
idx
=
1
;
static
void
add
(
int
a
,
int
b
)
{
e
[
cnt
]
=
b
;
ne
[
cnt
]
=
head
[
a
];
head
[
a
]
=
cnt
++;
e
[
idx
]
=
b
;
ne
[
idx
]
=
head
[
a
];
head
[
a
]
=
idx
++;
}
}
ACWing/src/dp/状态压缩dp/哈密尔顿回路.java
浏览文件 @
9f2a7a56
...
...
@@ -29,7 +29,7 @@ import static java.lang.Math.min;
* 18
* 状压dp
* 该图是完全图
* 2的整数次幂-1的二进制位全是1
111111
* 2的整数次幂-1的二进制位全是1
* f[i,j]状态表示为从0走到顶点j状态为i的所有走法
*/
public
class
哈密尔顿回路
{
...
...
ACWing/src/dp/状态压缩dp/骑士.java
浏览文件 @
9f2a7a56
...
...
@@ -39,10 +39,9 @@ import java.util.Scanner;
* 另外,a中的合法状态可以转移到哪些合法的状态,也可以预处理出来存进向量b中。
* 本题方案数可能很大,需要用long long存储。
* <p>
* f[i,j,k]
* f[i,j,k]
k为二进制数,表示在哪里放了国王
* 状态定义:所有只从前i行摆放,已经摆了j个国王,并且第i行的摆放状态是k的所有方案的集合
* 属性count
*
*/
public
class
骑士
{
public
static
void
main
(
String
[]
args
)
{
...
...
@@ -52,7 +51,7 @@ public class 骑士 {
for
(
int
i
=
0
;
i
<
1
<<
n
;
i
++)
{
if
(
check
(
i
))
{
a
.
add
(
i
);
//去除相邻的放置方法
cnt
.
add
(
count
(
i
));
cnt
.
add
(
count
(
i
));
//预处理i作为
}
}
int
s
=
0
,
t
=
0
,
u
=
0
;
...
...
ACWing/src/dp/状态机模型/大盗阿福.java
浏览文件 @
9f2a7a56
...
...
@@ -88,7 +88,12 @@ public class 大盗阿福 {
* 状态转移,看成图论问题
* f[i,0] f[i,1] 表示:所有走了i步,且当前位于状态j的所有走法
* 属性:max
* 状态计算:f[i,0] 0->0 上一个不偷,这个一个也不偷, f[i-1,0]
* 状态0代表没偷,状态1代表偷了
* 0->0
* 0->1
* 1->0
* 只有这三种转移方式
* 状态计算:f[i,0] 0->0 上一个不偷,这个一个也不偷, 对应就是f[i-1,0]
* 1->0 上一个偷了,这个不偷 f[i-1,1]
* f[i,1] 状态计算,只能0->1 上个不偷这个偷,f[i-1,0]+w[i]
*/
...
...
ACWing/src/dp/状态机模型/股票买卖4.java
浏览文件 @
9f2a7a56
...
...
@@ -47,6 +47,8 @@ import java.util.Scanner;
* f[i][j][1] = f[i-1][j][1],故f[i][j][1] = max(f[i-1][j][1],f[i-1][j-1][0]-w[i])。
* 从而状态转移方程就求出来了,下面考虑边界状态,f[i][0][0]表示第i天都未进行交易,
* 收益是0,除此之外,f[i][[j][0]与f[i][0][1]的初始状态都应该是不合法的,设置为-INF。
* <p>
* 引入一层状态用来存交易次数
*/
public
class
股票买卖4
{
public
static
void
main
(
String
[]
args
)
{
...
...
@@ -68,7 +70,7 @@ public class 股票买卖4 {
for
(
int
i
=
0
;
i
<=
n
;
i
++)
{
for
(
int
j
=
0
;
j
<=
k
;
j
++)
{
for
(
int
l
=
0
;
l
<
2
;
l
++)
{
f
[
i
][
j
][
l
]
=
Integer
.
MIN_VALUE
/
2
;
f
[
i
][
j
][
l
]
=
-
0x3f3f3f3f
;
}
}
}
//初始化负无穷
...
...
@@ -79,10 +81,12 @@ public class 股票买卖4 {
f
[
i
][
j
][
0
]
=
Math
.
max
(
f
[
i
-
1
][
j
][
0
],
f
[
i
-
1
][
j
][
1
]
+
a
[
i
]);
//卖出不消耗次数
f
[
i
][
j
][
1
]
=
Math
.
max
(
f
[
i
-
1
][
j
][
1
],
f
[
i
-
1
][
j
-
1
][
0
]
-
a
[
i
]);
//昨天买的,今天不
卖
, 昨天交易次数为j-1没买,今天买上
//昨天买的,今天不
动
, 昨天交易次数为j-1没买,今天买上
//买入消耗次数
}
}
//查看进行i次交易能得到利润最大值
int
res
=
0
;
for
(
int
i
=
0
;
i
<=
k
;
i
++)
{
res
=
Math
.
max
(
res
,
f
[
n
][
i
][
0
]);
...
...
ACWing/src/dp/背包模型/买书.java
浏览文件 @
9f2a7a56
...
...
@@ -46,7 +46,7 @@ public class 买书 {
}
static
int
n
=
400
;
static
int
v
[]
=
{
0
,
10
,
20
,
50
,
100
};
static
int
[]
v
=
{
0
,
10
,
20
,
50
,
100
};
static
int
[]
dp
=
new
int
[
1010
];
static
int
[][]
f
=
new
int
[
5
][
1010
];
}
ACWing/src/dp/背包模型/分组背包问题.java
浏览文件 @
9f2a7a56
...
...
@@ -5,8 +5,9 @@ import java.util.Scanner;
/**
* 有N组物品,每个组只能选1个,
* 求最大价值
*
转换成
01背包问题,
*
类似
01背包问题,
* 状态定义为f[i,j]:前i组物品可选,体积不超过j的所有选法最大值
* 属性max
* 划分依据,选第i组物品的第几个,还是不选第i组物品
* 状态划分:选第i组物品的第1个,选第i组物品的第2个,选第i组物品的第s[i]个,不选第i组物品
* 状态计算:显然不选第i组物品就是f[i-1,j]
...
...
ACWing/src/dp/背包模型/多重背包1.java
浏览文件 @
9f2a7a56
...
...
@@ -5,8 +5,10 @@ import java.util.Scanner;
/**
* 完全背包变形多重背包:每样物品最多选s[i]个
* 同理状态定义:f[i,j]代表体积为j前i个物品可选的最大价值
* 划分依据:选第i个物品多少个
* 状态划分:选0个第i个物品,选1个第i个物品,选2个第i个物品,选3个第i个物品....选s[i]个第i个物品
* 状态计算,不失一般性,选k个:f[i-1,j-k*v[i]]+w[i] 只有在j>=k*v[i]并且k<=s[i]的时候才合法
* O(n^3)
*/
public
class
多重背包1
{
public
static
void
main
(
String
[]
args
)
{
...
...
ACWing/src/dp/背包模型/多重背包二进制优化.java
浏览文件 @
9f2a7a56
...
...
@@ -17,6 +17,32 @@ import java.util.Scanner;
*/
public
class
多重背包二进制优化
{
public
static
void
main
(
String
[]
args
)
{
Scanner
sc
=
new
Scanner
(
System
.
in
);
N
=
sc
.
nextInt
();
V
=
sc
.
nextInt
();
int
a
,
b
,
c
;
for
(
int
i
=
1
;
i
<=
N
;
i
++)
{
v
[
i
]
=
sc
.
nextInt
();
w
[
i
]
=
sc
.
nextInt
();
s
[
i
]
=
sc
.
nextInt
();
}
for
(
int
i
=
1
;
i
<=
N
;
i
++)
{
for
(
int
k
=
1
;
k
<=
s
[
i
];
k
*=
2
)
{
//直接变成01背包
for
(
int
j
=
V
;
j
>=
v
[
i
];
j
--)
{
dp
[
j
]
=
Math
.
max
(
dp
[
j
-
v
[
i
]]
+
w
[
i
],
dp
[
j
]);
}
s
[
i
]
-=
k
;
}
if
(
s
[
i
]
>
0
)
{
for
(
int
j
=
V
;
j
>=
v
[
i
];
j
--)
{
dp
[
j
]
=
Math
.
max
(
dp
[
j
-
v
[
i
]]
+
w
[
i
],
dp
[
j
]);
}
}
}
System
.
out
.
println
(
dp
[
V
]);
}
static
void
yuchuli
()
{
Scanner
sc
=
new
Scanner
(
System
.
in
);
N
=
sc
.
nextInt
();
V
=
sc
.
nextInt
();
...
...
@@ -38,7 +64,7 @@ public class 多重背包二进制优化 {
v
[
cnt
]
=
a
*
c
;
w
[
cnt
]
=
b
*
c
;
}
}
}
//二进制预处理
N
=
cnt
;
//二进制优化后,一共有n个物品,01背包
for
(
int
i
=
1
;
i
<=
N
;
i
++)
{
for
(
int
j
=
V
;
j
>=
v
[
i
];
j
--)
{
...
...
@@ -48,8 +74,9 @@ public class 多重背包二进制优化 {
System
.
out
.
println
(
dp
[
V
]);
}
static
int
cnt
=
0
;
static
int
dp
[]
=
new
int
[
2010
];
static
int
cnt
=
0
;
static
int
[]
dp
=
new
int
[
2010
];
static
int
[]
v
=
new
int
[
1000
*
13
],
w
=
new
int
[
1000
*
13
];
static
int
[]
s
=
new
int
[
13000
];
static
int
N
,
V
;
}
ACWing/src/dp/背包模型/数字组合.java
浏览文件 @
9f2a7a56
...
...
@@ -23,11 +23,15 @@ import java.util.Scanner;
* M看做背包容量,每一个数看作物品,把Ai看做体积
* 求出总体积为M的所有方案数量
* 状态定义:f[i,j],集合:所有只从前i个物品选,且恰好总体积是j的方案总和
* 属性:count
* 属性:count
,方案数
* 状态划分:包含第i个,不包含第i个
* 划分依据:包不包含当前物品i
* 状态计算:不包含第i个->f[i-1,j]
* 包含第i个->f[i-1,j-v[i]]
* 状态合并:
* 显然:从前i个物品选且总体积恰好为j方案应当等于如下
* 前i-1种物品且总体积为j的方案加上前i-1种物品可选总体积恰好为j-v[i]
* 因为前i-1种物品可选总体积恰好为j-v[i]再加上第重量为v[i]的第i种物品恰好是一种合法方案
* 所以f[i,j]=f[i-1,j]+f[i-1,j-v[i]]
*/
public
class
数字组合
{
...
...
@@ -36,15 +40,15 @@ public class 数字组合 {
n
=
sc
.
nextInt
();
m
=
sc
.
nextInt
();
for
(
int
i
=
1
;
i
<=
n
;
i
++)
{
A
[
i
]
=
sc
.
nextInt
();
v
[
i
]
=
sc
.
nextInt
();
}
// one();
f
[
0
][
0
]
=
1
;
for
(
int
i
=
1
;
i
<=
n
;
i
++)
{
for
(
int
j
=
0
;
j
<=
m
;
j
++)
{
f
[
i
][
j
]
=
f
[
i
-
1
][
j
];
if
(
j
>=
A
[
i
])
f
[
i
][
j
]
+=
f
[
i
-
1
][
j
-
A
[
i
]];
if
(
j
>=
v
[
i
])
f
[
i
][
j
]
+=
f
[
i
-
1
][
j
-
v
[
i
]];
}
}
System
.
out
.
println
(
f
[
n
][
m
]);
...
...
@@ -54,14 +58,14 @@ public class 数字组合 {
static
void
one
()
{
dp
[
0
]
=
1
;
for
(
int
i
=
1
;
i
<=
n
;
i
++)
{
for
(
int
j
=
m
;
j
>=
A
[
i
];
j
--)
{
dp
[
j
]
+=
dp
[
j
-
A
[
i
]];
for
(
int
j
=
m
;
j
>=
v
[
i
];
j
--)
{
dp
[
j
]
+=
dp
[
j
-
v
[
i
]];
}
}
System
.
out
.
println
(
dp
[
m
]);
}
static
int
[]
A
=
new
int
[
110
];
static
int
[]
v
=
new
int
[
110
];
static
int
[][]
f
=
new
int
[
110
][
10010
];
static
int
[]
dp
=
new
int
[
10010
];
static
int
n
,
m
;
...
...
ACWing/src/dp/背包模型/普通二维费用背包.java
浏览文件 @
9f2a7a56
...
...
@@ -30,7 +30,7 @@ import java.util.Scanner;
* 输出样例:
* 8
* 分析:背包有重量和体积限制,每个物品可选可不选,求最大价值
* 状态表示:f[i,j,k] 所有只从前i种物品选,总体积超过j,总重量不超过k的选法
* 状态表示:f[i,j,k] 所有只从前i种物品选,总体积
不
超过j,总重量不超过k的选法
* 属性: max 最大价值
* 状态划分:所有包含第i个物品的选法,所有不包含物品i的选法
* 不选第i个物品:f[i-1,j,k]
...
...
ACWing/src/dp/背包模型/机器分配.java
浏览文件 @
9f2a7a56
...
...
@@ -29,12 +29,14 @@ import java.util.Scanner;
* 2 1
* 3 1
* 分析:
* 抽象为分组背包问题
* 本题相当于AcWing 9 分组背包问题问题。每组物品要么一个不选,
* 要么同一组最多选择其中的一个,本题每个公司可获得的设备数量也是只能选择一个,
* 故状态表示f[i][j]表示在前i家公司中选择分配不超过j台设备的最大盈利。
* 状态转移方程为f[i][j] = max(f[i-1][j-k]+w[i][k]),其中j >= k。
* 另外题目要求输出任意一组合法方案,所以用个数组存储方案即可,具体第i组物品选与不选,
* 如果选,选几个,只需要找出其中的一个k,使得f[i][j] == f[i-1][j-k]+w[i][k]即可使得第i个物品选k个是合法的方案。
* 如果选,选几个,只需要找出其中的一个k,
* 使得f[i][j] == f[i-1][j-k]+w[i][k]即可使得第i个物品选k个是合法的方案。
*/
public
class
机器分配
{
public
static
void
main
(
String
[]
args
)
{
...
...
@@ -59,8 +61,9 @@ public class 机器分配 {
int
j
=
m
;
for
(
int
i
=
n
;
i
!=
0
;
i
--)
{
//倒序往前找决策
for
(
int
k
=
0
;
k
<=
j
;
k
++)
{
//k从0开始使得存在不选第i组物品的方案
if
(
f
[
i
][
j
]
==
f
[
i
-
1
][
j
-
k
]
+
w
[
i
][
k
])
{
way
[
i
]
=
k
;
way
[
i
]
=
k
;
//这个是倒序存的,所以最终可以正序输出
j
-=
k
;
break
;
}
...
...
ACWing/src/dp/背包模型/混合背包.java
浏览文件 @
9f2a7a56
...
...
@@ -33,12 +33,13 @@ public class 混合背包 {
t
[
i
]
=
sc
.
nextInt
();
}
for
(
int
i
=
1
;
i
<=
N
;
i
++)
{
if
(
t
[
i
]
==
0
)
{
if
(
t
[
i
]
==
0
)
{
//完全背包
for
(
int
j
=
v
[
i
];
j
<=
V
;
j
++)
{
f
[
j
]
=
Math
.
max
(
f
[
j
],
f
[
j
-
v
[
i
]]
+
w
[
i
]);
}
}
else
{
if
(
t
[
i
]
==
-
1
)
t
[
i
]
=
1
;
if
(
t
[
i
]
==
-
1
)
t
[
i
]
=
1
;
//01背包
//多重背包转01背包
for
(
int
k
=
1
;
k
<=
t
[
i
];
k
*=
2
)
{
for
(
int
j
=
V
;
j
>=
k
*
v
[
i
];
j
--)
{
//把k个物品看成可选可不选的一个物品,01背包
f
[
j
]
=
Math
.
max
(
f
[
j
],
f
[
j
-
k
*
v
[
i
]]
+
w
[
i
]
*
k
);
...
...
ACWing/src/dp/背包模型/潜水员二维费用背包.java
浏览文件 @
9f2a7a56
...
...
@@ -35,6 +35,7 @@ import java.util.Scanner;
* 4 20 119
* 【输出样例】
* 249
* 最低状态定义稍有区别,状态定义恰好和至少的区别做法就不一样
* 显然三个东西,看如何划分:
* 物品: 氧气 氮气 重量
* a b c
...
...
@@ -51,6 +52,7 @@ import java.util.Scanner;
* 在状态定义恰好是j,恰好是k的时候
* f[0,0,0]=0 是合法的
* f[0,j,k]=是非法的,因为只选0个不可能达到恰好是j,或者k
* 应该f[0,j,k]=正无穷
*/
public
class
潜水员二维费用背包
{
public
static
void
main
(
String
[]
args
)
{
...
...
@@ -59,27 +61,27 @@ public class 潜水员二维费用背包 {
m
=
sc
.
nextInt
();
//需要的氮气
shu
=
sc
.
nextInt
();
//有多少个气缸
for
(
int
i
=
1
;
i
<=
shu
;
i
++)
{
o
[
i
]
=
sc
.
nextInt
();
d
[
i
]
=
sc
.
nextInt
();
v1
[
i
]
=
sc
.
nextInt
();
v2
[
i
]
=
sc
.
nextInt
();
w
[
i
]
=
sc
.
nextInt
();
}
two
();
}
static
int
n
,
m
,
shu
;
static
int
[]
o
=
new
int
[
1010
],
d
=
new
int
[
1010
],
w
=
new
int
[
1010
];
static
int
[]
v1
=
new
int
[
1010
],
v2
=
new
int
[
1010
],
w
=
new
int
[
1010
];
static
int
[][][]
f
=
new
int
[
23
][
88
][
1010
];
static
int
[][]
dp
=
new
int
[
5000
][
1600
];
static
void
two
()
{
for
(
int
i
=
0
;
i
<
dp
.
length
;
i
++
)
{
Arrays
.
fill
(
dp
[
i
],
Integer
.
MAX_VALUE
-
10000
);
for
(
int
[]
ints
:
dp
)
{
Arrays
.
fill
(
ints
,
0x3f3f3f3f
);
}
dp
[
0
][
0
]
=
0
;
for
(
int
i
=
1
;
i
<=
shu
;
i
++)
{
for
(
int
j
=
n
;
j
>=
0
;
j
--)
{
for
(
int
k
=
m
;
k
>=
0
;
k
--)
{
dp
[
j
][
k
]
=
Math
.
min
(
dp
[
j
][
k
],
dp
[
Math
.
max
(
j
-
o
[
i
],
0
)][
Math
.
max
(
k
-
d
[
i
],
0
)]
+
w
[
i
]);
dp
[
j
][
k
]
=
Math
.
min
(
dp
[
j
][
k
],
dp
[
Math
.
max
(
j
-
v1
[
i
],
0
)][
Math
.
max
(
k
-
v2
[
i
],
0
)]
+
w
[
i
]);
}
}
}
...
...
ACWing/src/dp/背包模型/背包问题求具体方案.java
浏览文件 @
9f2a7a56
...
...
@@ -28,9 +28,15 @@ import java.util.Scanner;
* 4 6
* 输出样例:
* 1 4
* f[i,j]=max(f[i-1,j],f[i-1,j-v[i]]+w[i])
* 其实判断出决策的是哪一项
* 对应图论最短路问题
* f[n-1,m]->f[n,m]边权重为0
* f[n-1,m-v[i]]+w[i]->f[n,m] 边权重为w[i]
* 也就是倒着求,f[n,m]是从哪一条边转移过来的
* 直接判断是f[n-1,m]==f[n,m]还是f[n-1,m-v[i]]+w[i]==f[n,m]
* 如果都相等,说明可选第i号物品,如果只有右边相等说明必选,如果只有左边相等说明不能选
* 就能判断决策
* 要求字典序最小:
* 可能最大价值有多种方案
* 对于一个物品:有三种情况,必选,可选,不能选
...
...
@@ -47,14 +53,14 @@ public class 背包问题求具体方案 {
v
[
i
]
=
sc
.
nextInt
();
w
[
i
]
=
sc
.
nextInt
();
}
for
(
int
i
=
n
;
i
>=
1
;
i
--)
{
for
(
int
i
=
n
;
i
>=
1
;
i
--)
{
//倒序枚举每个物品,方便倒推方案
for
(
int
j
=
0
;
j
<=
m
;
j
++)
{
f
[
i
][
j
]
=
f
[
i
+
1
][
j
];
if
(
j
>=
v
[
i
])
f
[
i
][
j
]
=
Math
.
max
(
f
[
i
][
j
],
f
[
i
+
1
][
j
-
v
[
i
]]
+
w
[
i
]);
}
}
//f[1][m]是最大值
//f[1][m]是最大值
,是结果
int
j
=
m
;
for
(
int
i
=
1
;
i
<=
n
;
i
++)
{
//1~n个物品可选
if
(
j
>=
v
[
i
]
&&
f
[
i
][
j
]
==
f
[
i
+
1
][
j
-
v
[
i
]]
+
w
[
i
])
{
...
...
ACWing/src/dp/背包模型/背包问题求方案数量.java
0 → 100644
浏览文件 @
9f2a7a56
package
dp.
背包模型
;
import
java.util.Arrays
;
import
java.util.Scanner
;
/**
* 有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。
* 第 i 件物品的体积是 vi,价值是 wi。
* 求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
* 输出 最优选法的方案数。注意答案可能很大,请输出答案模 10^9+7 的结果。
* 输入格式
* 第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
* 接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。
* 输出格式
* 输出一个整数,表示 方案数 模 109+7 的结果。
* 数据范围
* 0<N,V≤1000
* 0<vi,wi≤1000
* 输入样例
* 4 5
* 1 2
* 2 4
* 3 4
* 4 6
* 输出样例:
* 2
* 题目问最大价值的方案数量
* 而不是加满背包的方案数量
* 最短路(0,0)->通过各种路径到(n,m)最短路径的条数
* f[i,j]=max ( f[i-1,j] f[i-1,j-v[i]]+w[i] )
* 最优解,最短路的,起点到最后一条边的方案数累加到终点
* 当然有可能又多条最短路
* g[i,j]代表f[i,j]取最大值的数量
* g[i,j]的计算对于f[i-1,j]的转移就是g[i-1,j]
* 对于f[i-1,j-v]+w的转移g[i-1,j-v]
* 同时转移:g[i-1,j]+g[i-1,j-v]
*/
public
class
背包问题求方案数量
{
static
int
mod
=
(
int
)
(
1
e9
+
7
);
static
int
n
,
m
;
static
int
[]
f
=
new
int
[
1010
];
static
int
[]
g
=
new
int
[
1010
];
//存的的恰好
static
int
[]
v
=
new
int
[
1010
];
static
int
[]
w
=
new
int
[
1010
];
public
static
void
main
(
String
[]
args
)
{
Scanner
sc
=
new
Scanner
(
System
.
in
);
n
=
sc
.
nextInt
();
m
=
sc
.
nextInt
();
Arrays
.
fill
(
f
,
-
0x3f3f3f3f
);
f
[
0
]
=
0
;
g
[
0
]
=
1
;
for
(
int
i
=
1
;
i
<=
n
;
i
++)
{
v
[
i
]
=
sc
.
nextInt
();
w
[
i
]
=
sc
.
nextInt
();
}
for
(
int
i
=
1
;
i
<=
n
;
i
++)
{
for
(
int
j
=
m
;
j
>=
v
[
i
];
j
--)
{
int
maxv
=
Math
.
max
(
f
[
j
],
f
[
j
-
v
[
i
]]
+
w
[
i
]);
int
cnt
=
0
;
if
(
maxv
==
f
[
j
])
cnt
+=
g
[
j
];
if
(
maxv
==
f
[
j
-
v
[
i
]]
+
w
[
i
])
cnt
+=
g
[
j
-
v
[
i
]];
g
[
j
]
=
cnt
%
mod
;
f
[
j
]
=
maxv
;
}
}
int
res
=
0
;
for
(
int
i
=
0
;
i
<=
m
;
i
++)
{
res
=
Math
.
max
(
res
,
f
[
i
]);
}
int
cnt
=
0
;
for
(
int
i
=
0
;
i
<=
m
;
i
++)
{
if
(
res
==
f
[
i
])
{
cnt
=
(
cnt
+
g
[
i
])
%
mod
;
}
}
System
.
out
.
println
(
cnt
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录