luoguP1850 NOIP2016 换教室

luoguP1850 NOIP2016 换教室_第1张图片

luoguP1850 NOIP2016 换教室_第2张图片

analysis

这题如果往DP方向去想的话应该还是比较好想的

f [ i ] [ j ] [ 0..1 ] f[i][j][0..1] f[i][j][0..1]为前i间教室,用了j个机会申请,当前教室申不申请(0\1)

至于第三维的必要性,可以这样理解:

当前的决策为第i间教室是否申请,如果不用第3维,那么就不能够体现此决策,也无法转移

根据期望的定义,若随机变量x取值为xi的概率为pi,那么期望E就是

E ( x ) = ∑ x i × p i E_{(x)}=\sum x_i\times p_i E(x)=xi×pi

(这据说就是所谓全期望公式了)

那么这道题,对于第i节课和第i+1节课,消耗的体力值和第i节课,第i+1节课是否申请有关

于是套上期望公式,DP方程为:

f [ i ] [ j ] [ 0 ] = m i n ( f [ i − 1 ] [ j ] [ 1 ] + p [ i − 1 ] d i s [ d [ i − 1 ] ] [ c [ i − 1 ] ] + ( 1 − p [ i − 1 ] ) d i s [ c [ i − 1 ] ] [ c [ i ] ] , f [ i − 1 ] [ j ] [ 0 ] + d i s [ c [ i − 1 ] ] [ c [ i ] ] ) \begin{aligned} f[i][j][0]=min(f[i-1][j][1]+&p[i-1]dis[d[i-1]][c[i-1]]\\+&(1-p[i-1])dis[c[i-1]][c[i]],\\f[i-1][j][0]+&dis[c[i-1]][c[i]])\\ \end{aligned} f[i][j][0]=min(f[i1][j][1]++f[i1][j][0]+p[i1]dis[d[i1]][c[i1]](1p[i1])dis[c[i1]][c[i]],dis[c[i1]][c[i]])
f [ i ] [ j ] [ 1 ] = m i n ( f [ i − 1 ] [ j − 1 ] [ 1 ] + p [ i − 1 ] p [ i ] d i s [ d [ i − 1 ] ] [ d [ i ] ] + p [ i − 1 ] ( 1 − p [ i ] ) d i s [ d [ i − 1 ] ] [ c [ i ] ] + ( 1 − p [ i − 1 ] ) p [ i ] d i s [ c [ i − 1 ] ] [ d [ i ] ] + ( 1 − p [ i − 1 ] ) ( 1 − p [ i ] ) d i s [ c [ i − 1 ] ] [ c [ i ] ] , f [ i − 1 ] [ j − 1 ] [ 0 ] + p [ i ] d i s [ c [ i − 1 ] ] [ d [ i ] ] + ( 1 − p [ i ] ) d i s [ c [ i − 1 ] ] [ d [ i ] ] ) \begin{aligned} f[i][j][1]=min(f[i-1][j-1][1]+&p[i-1]p[i]dis[d[i-1]][d[i]]\\+&p[i-1](1-p[i])dis[d[i-1]][c[i]]\\+&(1-p[i-1])p[i]dis[c[i-1]][d[i]]\\+&(1-p[i-1])(1-p[i])dis[c[i-1]][c[i]],\\f[i-1][j-1][0]+&p[i]dis[c[i-1]][d[i]]\\+&(1-p[i])dis[c[i-1]][d[i]]) \end{aligned} f[i][j][1]=min(f[i1][j1][1]++++f[i1][j1][0]++p[i1]p[i]dis[d[i1]][d[i]]p[i1](1p[i])dis[d[i1]][c[i]](1p[i1])p[i]dis[c[i1]][d[i]](1p[i1])(1p[i])dis[c[i1]][c[i]],p[i]dis[c[i1]][d[i]](1p[i])dis[c[i1]][d[i]])

至于dis,可以用Floyd处理

code

#include
using namespace std;
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define anti_loop(i,start,end) for(register int i=start;i>=end;--i)
#define ll long long
template<typename T>void read(T &x){
	char r=getchar();T neg=1;x=0;
	while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
	while(r>='0'&&r<='9'){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
	x*=neg;
}
const int maxn=2000+10;
const int maxm=2000+10;
const int maxe=90000+10;
const int maxv=300+10;
int n,m,v,e;
int G[maxv][maxv],C[maxn],D[maxn];
double K[maxn],f[maxn][maxm][2];
int main(){
	#ifndef ONLINE_JUDGE
	//freopen("datain.txt","r",stdin);
	#endif
	clean(G,0x3f);
	read(n);read(m);read(v);read(e);
	loop(i,1,n)read(C[i]);
	loop(i,1,n)read(D[i]);
	loop(i,1,n)scanf("%lf",&K[i]);
	loop(i,1,e){
		int ui,vi,wi;
		read(ui);read(vi);read(wi);
		G[ui][vi]=min(G[ui][vi],wi);
		G[vi][ui]=G[ui][vi];
	}//input
	loop(k,1,v){
		loop(i,1,v){
			loop(j,1,v){
				if(i!=j)G[i][j]=min(G[i][j],G[i][k]+G[k][j]);
				else G[i][j]=0;
			}
		}
	}//floyd
	loop(i,1,n)
		loop(j,0,m)
			f[i][j][0]=f[i][j][1]=1e9;
	f[1][0][0]=0;
	f[1][1][1]=0;
	loop(i,2,n){
		loop(j,0,min(m,i)){
			f[i][j][0]=min(f[i-1][j][1]+
										K[i-1]*1.0*G[D[i-1]][C[i]]+
										(1-K[i-1])*1.0*G[C[i-1]][C[i]],
							f[i-1][j][0]+
										1.0*G[C[i-1]][C[i]]);
			if(j!=0)f[i][j][1]=min(f[i-1][j-1][0]+
										K[i]*1.0*G[C[i-1]][D[i]]+
										(1-K[i])*1.0*G[C[i-1]][C[i]],
							f[i-1][j-1][1]+
										K[i-1]*K[i]*1.0*G[D[i-1]][D[i]]+
										(1-K[i-1])*K[i]*G[C[i-1]][D[i]]+
										K[i-1]*(1-K[i])*1.0*G[D[i-1]][C[i]]+
										(1-K[i-1])*(1-K[i])*1.0*G[C[i-1]][C[i]]);
		}
	}//DP
	double res=1e9;
	loop(i,0,m){
		res=min(res,min(f[n][i][1],f[n][i][0]));
	}printf("%.2lf\n",res);
	return 0;
} 

你可能感兴趣的:(小蒟蒻的noip回头路,动态规划,数学)