noip2016 d1t3 换教室 期望dp+floyd

来源:互联网 发布:java 获取当天日期 编辑:程序博客网 时间:2024/05/26 05:51

题目描述


NOIP2016D1T3

Solution


题目巨长无比,数据解释巨长无比,数据表巨长无比,感觉这才是noip应该有的样子

期望dp,设f[i][j][1/0]表示第i时刻用了j次换教室的机会,现在换/不换的期望。跑一个floyd找最短路,枚举转移就可以了。

期望简而言之就是枚举出所有情况,把每一种情况的权值*概率再相加就是总的期望。对于这道题目就是判断一下第i-1天是否成功、第i天是否成功

一个坑点就是n和v代表着不同的东西,第一次不注意floyd跑挂了

Code


#include <stdio.h>#include <string.h>#include <algorithm>#define rep(i,st,ed) for (int i=st;i<=ed;++i)#define fill(x,t) memset(x,t,sizeof(x))#define INF 0x7fffffff#define N 2005using namespace std;double f[N][N][2],p[N];int dis[N][N],c[N],d[N];int n,m,v,e;void dp() {    rep(i,0,n) {        rep(j,0,m) {            f[i][j][0]=f[i][j][1]=INF;        }    }    f[1][1][1]=0;    f[1][0][0]=0;    rep(i,2,n) {        rep(j,0,min(i,m)) {            f[i][j][0]=min(f[i][j][0],(double)(f[i-1][j][0]+dis[c[i-1]][c[i]]));            if (j>0) {                f[i][j][0]=min(f[i][j][0],(double)                    (f[i-1][j][1]+dis[d[i-1]][c[i]])*p[i-1]+                    (f[i-1][j][1]+dis[c[i-1]][c[i]])*(1-p[i-1]));                f[i][j][1]=min(f[i][j][1],(double)                    (f[i-1][j-1][0]+dis[c[i-1]][d[i]])*p[i]+                    (f[i-1][j-1][0]+dis[c[i-1]][c[i]])*(1-p[i]));            }            if (j>1) {                f[i][j][1]=min(f[i][j][1],(double)                    (f[i-1][j-1][1]+dis[c[i-1]][c[i]])*(1-p[i-1])*(1-p[i])+                    (f[i-1][j-1][1]+dis[d[i-1]][c[i]])*p[i-1]*(1-p[i])+                    (f[i-1][j-1][1]+dis[c[i-1]][d[i]])*(1-p[i-1])*p[i]+                    (f[i-1][j-1][1]+dis[d[i-1]][d[i]])*p[i-1]*p[i]);            }        }    }    double ans=INF;    for (int i=0;i<=m;i++)        ans=min(ans,min(f[n][i][0],f[n][i][1]));    printf("%.2lf",ans);}void floyd() {    rep(k,1,v) {        rep(i,1,v) {            rep(j,1,v) {                if (i!=j&&i!=k&&j!=k&&dis[i][k]+dis[k][j]<dis[i][j]) {                    dis[i][j]=dis[i][k]+dis[k][j];                }            }        }    }}void init() {    fill(dis,63);    scanf("%d%d%d%d",&n,&m,&v,&e);    rep(i,1,v) dis[i][i]=0;    rep(i,1,n) scanf("%d",&c[i]);    rep(i,1,n) scanf("%d",&d[i]);    rep(i,1,n) scanf("%lf",&p[i]);    rep(i,1,e) {        int x,y,w;        scanf("%d%d%d",&x,&y,&w);        dis[x][y]=min(dis[x][y],w);        dis[y][x]=min(dis[y][x],w);    }}int main(void) {    init();    floyd();    dp();    return 0;}
原创粉丝点击