这题正解很短很简单,就是基础的概率期望题。
比赛的时候打floyd暴力可以过80分。
先用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申请成不成功的情况。
如果(j!=m)
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])
#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
#define rep(i,a) for(i=first[a];i;i=next[i])
using namespace std;
typedef long long ll;
const int maxn=2007,mo=1e9+7;
int i,j,k,l,t,n,m,v,e;
int a[maxn],b[maxn];
double gai[maxn];
int first[maxn*2],last[maxn*2],next[maxn*2],chang[maxn*2],num,ber;
double f[maxn][maxn][2];
int d[maxn][maxn];
bool bz[maxn];
double ans,ans1;
int cnt,cnt1;
void add(int x,int y,int z){
last[++num]=y,next[num]=first[x],first[x]=num;chang[num]=z;
}
int main(){
freopen("classroom.in","r",stdin);
freopen("classroom.out","w",stdout);
// freopen("fan.in","r",stdin);
scanf("%d%d%d%d",&n,&m,&v,&e);
fo(i,1,n)scanf("%d",&a[i]);
fo(i,1,n)scanf("%d",&b[i]);
fo(i,1,n)scanf("%lf",&gai[i]);
memset(d,127/2,sizeof(d));
fo(i,1,e){
scanf("%d%d%d",&k,&l,&t);
add(k,l,t);add(l,k,t);
d[k][l]=min(d[k][l],t);
d[l][k]=min(d[l][k],t);
}
fo(i,1,v)d[i][i]=0;
fo(k,1,v)fo(i,1,v)fo(j,1,v)if(d[i][k]+d[k][j]1,v)d[0][i]=0;
fo(i,0,2006)fo(j,0,2006)fo(k,0,1)f[i][j][k]=99999999999;
f[0][0][0]=0;
fo(i,0,n-1){
fo(j,0,m){
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]]);
if(j!=m)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]);
}
}
ans=99999999999;
fo(j,0,m)ans=min(ans,min(f[n][j][0],f[n][j][1]));
printf("%.2lf\n",ans);
return 0;
}