洛谷 P1850 [NOIP2016 提高组] 换教室 做题记录
神经期望 dp 题。
设 \(f_{i,j,0/1}\) 表示现在是第 \(i\) 节课,到现在换了 \(j\) 节课,第 \(i-1\) 节课换了/没换。
显而易见的,我们有:
\(f_{i,j,0}=\min(f_{i-1,j,0}+dis_{c_{i-1},c_i},f_{i-1,j,1}+k_{i-1}\times dis_{d_{i-1},c_i}+(1-k_{i-1})\times dis_{c_{i-1},c_{i}})\)
\(f_{i,j,1}=\min(f_{i-1,j-1,0} + k_i\times dis_{c_{i-1},d_i}+(1-k_i)\times dis_{c_{i-1},c_i}, \\ f_{i-1,j-1,1}+k_i k_{i-1} \times dis_{d_{i-1},d_i} + k_i(1-k_{i-1})\times dis_{c_{i-1},d_{i}} + (1-k_{i})k_{i-1} \times dis_{d_{i-1},c_i}+ (1-k_i)(1-k_{i-1})\times dis_{c_{i-1},c_{i}})\)
因为 \(v\le 200\),算 \(dis\) 时跑一个 floyd 就好了。
点击查看代码
#include<bits/stdc++.h>
#define mem(a,b) memset((a),(b),sizeof(a))
#define m0(a) memset((a),0,sizeof(a))
#define lb(x) ((x)&-(x))
#define lc(x) ((x)<<1)
#define rc(x) (((x)<<1)|1)
#define pb(G,x) (G).push_back((x))
#define For(a,b,c) for(int a=(b);a<=(c);a++)
#define Rep(a,b,c) for(int a=(b);a>=(c);a--)
#define in1(a) a=read()
#define in2(a,b) a=read(), b=read()
#define in3(a,b,c) a=read(), b=read(), c=read()
#define inn(i,n,a) For(i,1,n) a[i]=read();
#define ll long long
#define i128 __int128
using namespace std;
inline int read() {
int xx= 0;int f= 1;
char c = getchar();
while(c<'0'||c>'9') {
if(c=='-') f= -1;
c= getchar();
}
while(c>='0'&&c<='9') {
xx= (xx<<1)+(xx<<3)+(c^48);
c= getchar();
}
return xx*f;
}
#define maxn 200050
long double f[2050][2050][2];
int n,m,v,e;
int c[2050],d[2050];
long double k[2050];
int dis[305][305];
signed main() {
in2(n,m); in2(v,e);
For(i,1,n) in1(c[i]);
For(i,1,n) in1(d[i]);
mem(dis,0x3f);
For(i,1,n) scanf("%Lf",&k[i]);
For(i,1,e) {
int x,y,z;
in3(x,y,z);
dis[x][y]=dis[y][x]=min(dis[x][y],z);
}
For(i,0,2020) For(j,0,2020) For(K,0,1) f[i][j][K]=1e18;
f[1][0][0]=f[1][1][1]=0;
For(i,1,v) dis[i][i]=0;
For(k,1,v) For(i,1,v) For(j,1,v) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
For(i,2,n) For(j,0,m) {
int a1=c[i-1],b1=d[i-1],a2=c[i],b2=d[i];
f[i][j][0]=min(f[i][j][0],min(f[i-1][j][0]+dis[a1][a2],f[i-1][j][1]+dis[b1][a2]*k[i-1]+dis[a1][a2]*(1-k[i-1])));
if(j>0)
f[i][j][1]=min(f[i][j][1],min(f[i-1][j-1][0]+k[i]*dis[a1][b2]+(1-k[i])*dis[a1][a2],
f[i-1][j-1][1]+k[i-1]*k[i]*dis[b1][b2]+
k[i-1]*(1-k[i])*dis[b1][a2]+
(1-k[i-1])*k[i]*dis[a1][b2]+
(1-k[i-1])*(1-k[i])*dis[a1][a2]));
}
long double ans=1e18;
For(i,0,m) ans=min(ans,f[n][i][0]),ans=min(ans,f[n][i][1]);
printf("%.2Lf",ans);
}
本文来自博客园,作者:coding_goat_qwq,转载请注明原文链接:https://www.cnblogs.com/CodingGoat/p/18498860