BZOJ 4720: [Noip2016]换教室

网上题解大致都有

我只是贴上来标记一下而已

总的来说测试时没有去考虑这一题是比较可惜的,因为没有看过太多关于期望的题就直接放弃了

只能说细节比较多,推方程什么的中规中矩不算难吧

只是还是参考了一下别人的罢了


#include<cstdio>
#include<algorithm>
#define RG register
#define INF 2e8
using namespace std;

inline int read()
{
    int a=0,f=1;static char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){a=a*10+c-'0';c=getchar();}
	return a*f;
}

int n,m,v,e;
int c[2001],d[2001],dis[301][301];
double p[2001],f[2001][2001][2];		//f[i][j][1/0]表示在第i个时间段,第j次申请,1/0表示是否申请成功

void floyd()
{
	RG int i,j,k;
	for(k=1;k<=v;++k)
		for(i=1;i<=v;++i)
			for(j=1;j<=v;++j)
				if(i!=j&&j!=k)
					dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}


int main()
{
	n=read(),m=read(),v=read(),e=read();
	RG int i,j;
	for(i=1;i<=n;++i) c[i]=read();
	for(i=1;i<=n;++i) d[i]=read();
    for(i=1;i<=n;++i) scanf("%lf",&p[i]);
    for(i=1;i<=v;++i)
	{
		for(j=1;j<=v;++j) dis[i][j]=INF;
		dis[i][i]=0;
    }
	for(i=1;i<=e;++i)
	{
		int x=read(),y=read(),z=read();
		dis[x][y]=min(dis[x][y],z);
		dis[y][x]=dis[x][y];
	}
	floyd();
	for(i=1;i<=n;++i)
		for(j=0;j<=m;++j)
			f[i][j][0]=f[i][j][1]=INF;
	f[1][0][0]=f[1][1][1]=0;
	for(i=2;i<=n;++i)
		for(j=0;j<=min(i,m);++j)
		{
			int cc=dis[c[i-1]][c[i]],cd=dis[c[i-1]][d[i]],dc=dis[d[i-1]][c[i]],dd=dis[d[i-1]][d[i]];
			double p1=p[i-1],p2=p[i];
			if(j<=i-1) f[i][j][0]=min(p1*dc+(1-p1)*cc+f[i-1][j][1],cc+f[i-1][j][0]);
			if(j>0) f[i][j][1]=min(f[i-1][j-1][0]+p2*cd+(1-p2)*cc,f[i-1][j-1][1]+p1*p2*dd+p1*(1-p2)*dc+(1-p1)*p2*cd+(1-p1)*(1-p2)*cc);//总之不是很难就对了
		}
	double ans=INF;
	for(i=0;i<=min(n,m);++i)
		ans=min(ans,min(f[n][i][0],f[n][i][1]));
    printf("%.2lf\n",ans);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值