洛谷 P1850 [NOIP2016 提高組] 換教室 做題記錄

coding_goat_qwq發表於2024-10-24

神經期望 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);
}

相關文章