[BZOJ4720][NOIP2016] 换教室
$solution:$
考虑 $f(i,j,k)$ 表示前 $i$ 个时间中申请 $j$ 个的最小距离期望,且是否申请。
然后分别讨论 $i-1$ 与$i$ 换还是不换且是否成功即可。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<climits> using namespace std; inline int read(){ int f=1,ans=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int N=2001; const int M=2001; const int MAXN=2001; int head[MAXN],n,m,v,e,cnt; struct node{ int u,v,w,nex; }x[180001]; priority_queue<pair<int,int> > que; void add(int u,int v,int w){ x[cnt].u=u,x[cnt].v=v,x[cnt].w=w,x[cnt].nex=head[u],head[u]=cnt++; } int A[MAXN],B[MAXN],dis[MAXN],Dis[MAXN][MAXN],vis[MAXN]; double p[MAXN],f[N][M][2]; void dijkstra(int S){ memset(vis,0,sizeof(vis)); memset(dis,127/3,sizeof(dis));dis[S]=0; que.push(make_pair(0,S)); while(!que.empty()){ int xx=que.top().second;que.pop(); if(vis[xx]) continue; Dis[S][xx]=dis[xx]; vis[xx]=1; for(int i=head[xx];i!=-1;i=x[i].nex){ if(dis[x[i].v]>dis[xx]+x[i].w){ dis[x[i].v]=dis[xx]+x[i].w; que.push(make_pair(-dis[x[i].v],x[i].v)); } } }return; } int main(){ //freopen("2.in","r",stdin); memset(head,-1,sizeof(head)); n=read(),m=read(),v=read(),e=read(); for(int i=1;i<=n;i++) A[i]=read(); for(int i=1;i<=n;i++) B[i]=read(); for(int i=1;i<=n;i++) scanf("%lf",&p[i]); memset(Dis,127/3,sizeof(Dis)); for(int i=1;i<=v;i++) Dis[i][i]=0; for(int i=1;i<=e;i++){int u=read(),v=read(),w=read();Dis[u][v]=min(Dis[u][v],w);Dis[v][u]=Dis[u][v];} for(int k=1;k<=v;k++) for(int i=1;i<=v;i++) for(int j=1;j<=v;j++) Dis[i][j]=min(Dis[i][j],Dis[i][k]+Dis[k][j]); for(int i=1;i<=n;i++) dijkstra(i); for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) f[i][j][0]=f[i][j][1]=(double)INT_MAX; double minn=f[0][0][0]; f[1][0][0]=0,f[1][1][1]=0; for(int i=2;i<=n;i++){ for(int j=0;j<=m;j++){ f[i][j][0]=min( f[i-1][j][1]+ p[i-1]*Dis[B[i-1]][A[i]] + (1-p[i-1])*Dis[A[i-1]][A[i]] , f[i-1][j][0]+Dis[A[i-1]][A[i]] ); if(j!=0) f[i][j][1]=min( f[i-1][j-1][1] + p[i-1]*p[i]*Dis[B[i-1]][B[i]] + p[i-1]*(1-p[i])*Dis[B[i-1]][A[i]] + (1-p[i-1])*p[i]*Dis[A[i-1]][B[i]] + (1-p[i-1])*(1-p[i])*Dis[A[i-1]][A[i]],f[i-1][j-1][0] + p[i]*Dis[A[i-1]][B[i]] + (1-p[i])*Dis[A[i-1]][A[i]]); //printf("f(%d,%d,0):%.3lf f(%d,%d,1):%.3lf\n",i,j,f[i][j][0],i,j,f[i][j][1]); } } //for(int i=0;i<=m;i++) printf("%.2lf %.2lf\n",f[n][i][0],f[n][i][1]); for(int i=0;i<=m;i++) minn=min(minn,min(f[n][i][0],f[n][i][1])); printf("%.2lf\n",minn); return 0; }/* 3 2 3 3 2 1 2 1 2 1 0.8 0.2 0.5 1 2 5 1 3 3 2 3 1 */