解题报告:
noip首次考期望dp
先用floyd预处理一下。
设f[i][j][k]表示第i个时间段,选了j个教室要申请(不一定成功),k表示i申请或不申请。
我们从i推到i+1,如果要推到f[i+1][j][0]的话,那么第i+1个时间段肯定在a[i+1]。这个可以从i的0状态和1状态推过来,如果从0推过来,那么i时间段肯定在a[i]这个地方,那么期望是d[a[i]][a[i+1]],概率是1。如果从1推过来,那么i有两种情况,申请成功和申请不成功,所以i时间段可能在a[i]或b[i],概率为1-gai[i]和gai[i]。
所以f[i+1][j][0]=min(f[i][j][0]+d[a[i]][a[i+1]],f[i][j][1]+(1−gai[i])∗d[a[i]][a[i+1]]+gai[i]∗d[b[i]][a[i+1]]);
要推倒f[i+1][j][1]情况类似,不过要考虑i+1申请成不成功的情况。
f[i+1][j+1][1]=min(f[i][j][0]+d[a[i]][b[i+1]]∗gai[i+1]+d[a[i]][a[i+1]]∗(1−gai[i+1]) ,f[i][j][1]+d[a[i]][a[i+1]]∗(1−gai[i])∗(1−gai[i+1])+d[b[i]][a[i+1]]∗gai[i]∗(1−gai[i+1])+d[a[i]][b[i+1]]∗(1−gai[i])∗gai[i+1]+d[b[i]][b[i+1]]∗gai[i]∗gai[i+1]);
最后答案就是min(f[n][j][0,1])
时间复杂度O(n3)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
int getint()
{
int i=0;char c;
for(c=getchar();c<'0'||c>'9';c=getchar());
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i;
}
const int N=2005,M=305,INF=0x3f3f3f3f;
int n,m,v,e;
int a[N],b[N],d[M][M];
double ans,p[N],f[N][N][2];
int main()
{
//freopen("lx.in","r",stdin);
int x,y,z;
memset(d,INF,sizeof(d));
ans=INF;
n=getint(),m=getint(),v=getint(),e=getint();
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
f[i][j][0]=f[i][j][1]=INF;
for(int i=1;i<=n;i++)a[i]=getint();
for(int i=1;i<=n;i++)b[i]=getint();
for(int i=1;i<=n;i++)scanf("%lf",&p[i]);
for(int i=1;i<=e;i++)
{
x=getint(),y=getint(),z=getint();
d[x][y]=min(d[x][y],z),d[y][x]=min(d[y][x],z);
}
for(int i=1;i<=v;i++)d[i][i]=0;
for(int k=1;k<=v;k++)
for(int i=1;i<=v;i++)
for(int j=1;j<=v;j++)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
f[1][1][1]=f[1][0][0]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
{
f[i+1][j][0]=min(f[i][j][0]+d[a[i]][a[i+1]],f[i][j][1]+p[i]*d[b[i]][a[i+1]]+(1-p[i])*(d[a[i]][a[i+1]]));
f[i+1][j+1][1]=min(f[i][j][0]+p[i+1]*d[a[i]][b[i+1]]+(1-p[i+1])*d[a[i]][a[i+1]],f[i][j][1]+p[i]*p[i+1]*d[b[i]][b[i+1]]+p[i]*(1-p[i+1])*d[b[i]][a[i+1]]+(1-p[i])*p[i+1]*d[a[i]][b[i+1]]+(1-p[i])*(1-p[i+1])*d[a[i]][a[i+1]]);
}
for(int i=0;i<=m;i++)
ans=min(ans,min(f[n][i][0],f[n][i][1]));
printf("%0.2f",ans);
return 0;
}