期望反映了一个随机变量的平均结果,是所有可能结果的概率乘上结果的和。例如对于一个随机变量x,1/3几率变为1,1/3几率变为2,1/3几率变为3,则x的期望值为
期望具有线性性质,我们可以根据加法原理和乘法原理来对期望进行计算
可以发现,最终方案是某种决策集合,而决策是没有概率的,所以每个状态应该取一个最优决策的期望消费,而不是各种决策搞一下期望和什么的,期望体力是确定的,能使期望体力不同是决策不同的原因
就是。。。一个状态只能由前面阶段的一个状态转移过来,因为一个人不能同时处于两种状态,最终方案是每个决断取了一个决策构成的集合
设
f(i,j,0/1)
f
(
i
,
j
,
0
/
1
)
表示到了第i节课,申请j次,第i节课是否申请的最小体力期望(申请需要一次提交)
那么转移就要在多重情况中取最优的,分别为:
i不申请,i-1申请成功
i不申请,i-1申请失败
i申请成功,i-1申请成功
i申请成功,i-1申请失败
i申请失败,i-1申请成功
i申请失败,i-1申请失败
不提交任何申请
具体的转移方程看代码吧。。。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int MAXN = 2000 + 10;
int n,m,v,e,c[MAXN],d[MAXN];
double g[310][310],k[MAXN],f[MAXN][MAXN][2],ans = 1e30;
void floyed() {
for(int k=1; k<=v; k++)
for(int i=1; i<=v; i++)
for(int j=1; j<=v; j++)
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
}
void solve() {
for(int i=2; i<=n; i++)
for(int j=0; j<=m; j++)
if(j==0)
f[i][j][0] = f[i-1][j][0] + g[c[i-1]][c[i]];
else {
f[i][j][0] = min( f[i-1][j][0] + g[c[i-1]][c[i]], f[i-1][j][1] + g[d[i-1]][c[i]] * k[i-1] + g[c[i-1]][c[i]] * (1-k[i-1]) );
f[i][j][1] = min( f[i-1][j-1][0] + g[c[i-1]][d[i]] * k[i] + g[c[i-1]][c[i]] * (1-k[i]),
f[i-1][j-1][1]
+ g[d[i-1]][d[i]] * k[i-1] * k[i]
+ g[d[i-1]][c[i]] * k[i-1] *(1-k[i])
+ g[c[i-1]][d[i]] * (1-k[i-1]) * k[i]
+ g[c[i-1]][c[i]] * (1-k[i-1]) * (1-k[i]) );
}
}
int main() {
cin >> n >> m >> v >> e;
for(int i=1; i<=n; i++)
cin >> c[i];
for(int i=1; i<=n; i++)
cin >> d[i];
for(int i=1; i<=n; i++)
cin >> k[i];
for(int i=1; i<=v; i++) {
for(int j=1; j<=v; j++)
g[i][j] = 1e30;
g[i][i] = 0;
}
for(int i=0; i<=n; i++)
for(int j=0; j<=m; j++)
f[i][j][0] = f[i][j][1] = 1e30;
for(int i=1; i<=e; i++) {
int a, b;
double z;
cin >> a >> b >> z;
g[a][b] = g[b][a] = min(g[a][b], z);
}
floyed();
f[1][0][0] = 0;
f[1][1][1] = 0;
solve();
ans = 1e30;
for(int i=0; i<=m; i++)
ans = min(ans, min(f[n][i][0], f[n][i][1]));
printf("%.2lf",ans);
return 0;
}