洛谷 P1850 [NOIP2016 提高组] 换教室 做题记录

神经期望 dp 题。
fi,j,0/1 表示现在是第 i 节课,到现在换了 j 节课,第 i1 节课换了/没换。
显而易见的,我们有:
fi,j,0=min(fi1,j,0+disci1,ci,fi1,j,1+ki1×disdi1,ci+(1ki1)×disci1,ci)

fi,j,1=min(fi1,j1,0+ki×disci1,di+(1ki)×disci1,ci,fi1,j1,1+kiki1×disdi1,di+ki(1ki1)×disci1,di+(1ki)ki1×disdi1,ci+(1ki)(1ki1)×disci1,ci)

因为 v200,算 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);
}
posted @   coding_goat_qwq  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示