期望DP入门(p1850换教室)

 

 

第一个,期望dp所有的情况一定要考虑好,每个现状态都由前一个状态转移而来,所以无论是前一个状态通过怎样的方式,两状态的起点终点如何,都应加在一起。此题关系到前一个是否成功和后一个是否成功,分别为

i-1决定换教室,i决定换教室时 (i-1成功换教室+i失败换教室) (i-1成功换教室+i成功换教室) (i-1失败换教室+i失败换教室) (i-1失败换教室+i成功换教室)

i-1决定换教室,i决定不换教室(i-1成功换教室+i不换教室) (i-1失败换教室+i不换教室) 

i-1决定不换教室,i决定换教室 (i-1不换教室+i成功换教室) (i-1不换教室+i失败换教室)

i-1决定不换教室,i决定不换教室 (i-1不换教室+i不换教室)

 

 

第二个,memset是绝对tmd不能用在double型数组上的。你会si掉。

第三个,判重边邻接矩阵可以简单这样搞:dis[x][y]=dis[y][x]=min(z,dis[x][y]);如果遇见vector或链式前向星或邻接矩阵都可以:map <pair<int,int>,bool> q;if(q[make_pair(a,b)]) continue;

第四个, double型的读入为%lf而非%llf。(被坑惨了)

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n,m,v,e,dis[302][302],a[2003],b[2003],x,y,z;
double k[2003],a2,a3,f[2003][2003][2];

void foll(){
    for(int k=1;k<=v;k++)
        for(int i=1;i<=v;i++)
            for(int j=1;j<=v;j++)
                if(dis[i][j]>dis[i][k]+dis[k][j])
                    dis[i][j]=dis[i][k]+dis[k][j];
}

void DP(){
    for(int i=2;i<=n;i++){
        for(int j=0;j<=min(i,m);j++){
            int m1=dis[a[i-1]][a[i]],m2=dis[a[i-1]][b[i]],m3=dis[b[i-1]][a[i]],m4=dis[b[i-1]][b[i]];
            f[i][j][0]=min(f[i-1][j][1]+m3*k[i-1]+m1*(1-k[i-1]),f[i-1][j][0]+m1);
            if(j>=1)
                f[i][j][1]=min(f[i-1][j-1][1]+m4*k[i-1]*k[i]+m2*(1-k[i-1])*k[i]+m1*(1-k[i-1])*(1-k[i])+m3*k[i-1]*(1-k[i]),f[i-1][j-1][0]+dis[a[i-1]][b[i]]*k[i]+dis[a[i-1]][a[i]]*(1-k[i]));
        }
    }
}

int main(){
    scanf("%d%d%d%d",&n,&m,&v,&e);
    for(int i=1;i<=300;i++)
        for(int j=1;j<=300;j++)    dis[i][j]=99999999;
    for(int i=1;i<=300;i++)    dis[i][i]=0;
    
    for(int i=1;i<=n;i++)
        for(int j=0;j<=m;j++)
            f[i][j][1]=f[i][j][0]=99999999;
    f[1][0][0]=f[1][1][1]=f[1][1][0]=0;
    for(int i=1;i<=n;i++)    scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)    scanf("%d",&b[i]);
    for(int i=1;i<=n;i++)    scanf("%lf",&k[i]);
    for(int i=1;i<=e;i++){
        scanf("%d%d%d",&x,&y,&z);
        dis[x][y]=dis[y][x]=min(z,dis[x][y]);
    }

    foll();
    DP();
    double ans=99999999;
    for(int i=0;i<=m;i++)
        ans=min(ans,min(f[n][i][1],f[n][i][0]));
    printf("%.2lf",ans);
    return 0;
}
View Code

 

posted @ 2019-08-19 16:50  sdzmq  阅读(194)  评论(0编辑  收藏  举报