问题应用_资源分配问题
问题描述
将 n n n个资源分配给 r r r个项目,已知如果把 j j j个资源分配给第 i i i个项目,可以收益 N ( i , j ) , 0 ≤ j ≤ n , 1 ≤ i ≤ r N(i,j),0 \leq j \leq n,1 \leq i \leq r N(i,j),0≤j≤n,1≤i≤r,求总收益最大的资源分配方案。
问题分析
1.用
r
+
1
r+1
r+1段图描述
2.每个状态节点
V
(
i
,
j
)
V(i,j)
V(i,j)代表已将
j
j
j个资源分配给前
i
−
1
i-1
i−1个项目
3.边都具有
(
V
(
i
,
j
)
,
V
(
i
+
1
,
k
)
)
(
0
≤
j
≤
k
≤
n
,
1
≤
i
≤
r
)
(V(i,j),V(i+1,k))(0 \leq j \leq k \leq n,1 \leq i \leq r)
(V(i,j),V(i+1,k))(0≤j≤k≤n,1≤i≤r)
4.边上的权值
N
(
i
,
k
−
j
)
N(i,k-j)
N(i,k−j)是本次分配的收益
5.
r
+
1
r+1
r+1个阶段
- 第一个阶段:开始阶段尚未分配任何资源,只包含一个初始状态 S = V ( 1 , 0 ) S=V(1,0) S=V(1,0)
- 第 r + 1 r+1 r+1阶段:结束阶段,表示整个分配完成,只有一个结束状态 t = V ( r + 1 , n ) t=V(r+1,n) t=V(r+1,n)
- 其他 r − 1 r-1 r−1个中间阶段:每个阶段包含 n + 1 n+1 n+1个状态
多段图问题
多段图概述
设图
G
=
(
V
,
E
)
G =(V,E)
G=(V,E)是一个带权有向图,如果把顶点集合
V
V
V 划分成
k
k
k个互不相交的子集
V
i
(
2
≤
k
≤
n
,
1
≤
i
≤
k
)
V_i(2\leq k\leq n,1\leq i\leq k)
Vi(2≤k≤n,1≤i≤k),使得
E
E
E 中的任何一条边
<
u
,
v
>
<u,v>
<u,v>,必有
u
∈
V
i
,
v
∈
V
i
+
m
(
1
≤
i
<
k
,
1
<
i
+
m
≤
k
)
u∈Vi, v∈Vi + m(1\leq i < k, 1<i+m\leq k)
u∈Vi,v∈Vi+m(1≤i<k,1<i+m≤k),则称图
G
G
G 为多段图,称
s
∈
V
1
s∈V_1
s∈V1 为源点,
t
∈
V
k
t∈V_k
t∈Vk 为终点。多段图的最短路径问题为从源点到终点的最小代价路径。
递推关系
(从后)向前递推关系式
{
c
o
s
t
(
i
,
j
)
=
min
j
∈
V
i
,
p
∈
V
i
+
1
,
<
i
,
p
>
∈
E
{
c
(
j
,
p
)
+
c
o
s
t
(
i
+
1
,
p
)
}
if
0
≤
i
≤
k
−
2
c
o
s
t
(
k
,
t
)
=
0
\begin{cases} cost(i,j)= \min\limits_{j∈V_i,p∈V_{i+1},<i,p>∈E} \{c(j,p)+cost(i+1,p)\} &\text{if } 0\leq i \leq k-2 \\ cost(k,t)=0 \end{cases}
⎩⎨⎧cost(i,j)=j∈Vi,p∈Vi+1,<i,p>∈Emin{c(j,p)+cost(i+1,p)}cost(k,t)=0if 0≤i≤k−2
c
o
s
t
(
i
,
j
)
cost(i,j)
cost(i,j)是从第
i
i
i阶段中某个节点状态
j
j
j到汇点状态
t
t
t的最短路径长度,
c
o
s
t
(
1
,
0
)
cost(1,0)
cost(1,0)为多段图问题的最优解值,即为所求。
设
d
(
i
,
j
)
d(i,j)
d(i,j)表示从第
i
i
i阶段节点
j
j
j到
t
t
t的最短路径上节点
j
j
j的下一个节点编号,利用
d
d
d值进行反向追溯可确定最短路径上的节点。
程序设计
- 数据结构:采用邻接表存储该有向无环图的节点及边的信息
- 源点 s s s编号为0,汇点的编号为 n − 1 n-1 n−1(共有 n n n节点, m m m条边)
- c o s t [ i ] cost[i] cost[i]保存节点 i i i到汇点 t t t的最短路径长度
- c o s t [ n − 1 ] cost[n-1] cost[n−1]为0,汇点到汇点的最短路径长度为0
- c o s t [ 0 ] cost[0] cost[0]为最优解值,为计算 c o s t [ j ] cost[j] cost[j],必须计算子问题:后继节点 p p p到汇点的最短路径 c o s t [ p ] cost[p] cost[p]
- c o s t [ j ] = min { c ( j , p ) + c o s t [ p ] } cost[j]=\min\{c(j,p)+cost[p]\} cost[j]=min{c(j,p)+cost[p]}, c ( j , p ) c(j,p) c(j,p)为边 < j , p > <j,p> <j,p>的长度(权)
代码
- 节点结构
Struct ENode{
int adjVex;
int w;
ENode *nextArc
}
- 其他变量
vector<Struct ENode> a;//邻接表,数组中存节点
vector<int> cost;//最短长度
int n;//总节点数
int m;//总边数
- 构建邻接表
void CreatGraph(){
int u,v;
int w;
Struct ENode t;
for(int i = 0;i < n;i ++){
a.push_back(t);
}
for(int i = 0;i < m;i ++){
cin >> u >> v >> w;
t->adjVex = v;
t->nextArc = a[u];
t->w = w;
a[u] = t;
}
}
- 向前递推算法
void FMultiGraph(){
cost[n-1] = 0;
int min;
Struct ENode r;
for(int i = n-2;i >= 0;i --){
min = max;
for(Struct ENode r = a[i];r;r = r->nextArc){
if(r->w + cost[r->adjVex] < min){
min = r->w + cost[r->adjVex];
}
}
cost[i] = min;
}
}
结束语
旅人等在这里,虔诚仰望着云开