AcWing233 换教室(数学)

这道题有意思的地方是,他要求提前决策,不能实时决策,这个意思是,我们不能记录当前点是否成功的状态,而只能记录是否申请的状态。

这道题比较明显的状态是f[][][],前i个,申请了j次,第i个有无申请。

但是我想通过记忆化搜索来做,因此将这个状态设计为前i-1个,申请了j次,第i-1个有无申请。这样初始状态就只有一种1,0,0,表示0的位置,申请0次,第0个没申请

因为我们根本没有第0个,所以只有他是合法的。

问的是最短路,只要floyd跑一下就行

在记忆化的时候,有很多情况

当i-1个没申请,那么我们i个可以申请或不申请

当i-1个申请了,同理。

当两个都申请了的话,就有4种情况,都没申请就是1种,其他都是两种

注意当已经申请等于m次,就不能再申请,因此要特判,细节比较多。一般floyd就用邻接矩阵存,注意初始化

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<map>
#include<string>
#include<vector>
using namespace std;
const int N=2010;
int n,m,v,e;
int g[N][N];
int pos[N][2];
double p[N];
double f[N][N][2];
void floyd(){
    int k,i,j;
    for(i=1;i<=v;i++)
    g[i][i]=0;
    for(k=1;k<=v;k++){
        for(i=1;i<=v;i++){
            for(j=1;j<=v;j++)
            g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
        }
    }
    for(int j=0;j<=v;j++) g[0][j] = 0;
}
double dfs(int i,int j,int flag){
    if(i==n+1)
    return 0;
    auto &x=f[i][j][flag];
    if(x!=-1)
    return x;
    double ans1=0;
    double ans0=0;
    if(flag==0) ans0 = dfs(i+1, j, 0) + g[pos[i-1][0]][pos[i][0]];
    else ans0 = dfs(i+1, j, 0) + p[i-1]*g[pos[i-1][1]][pos[i][0]] + (1-p[i-1])*g[pos[i-1][0]][pos[i][0]];
    if(j==m) return x= ans0;
    if(!flag){
        ans1=p[i]*(dfs(i+1,j+1,1)+g[pos[i-1][0]][pos[i][1]])+(1-p[i])*(dfs(i+1,j+1,1)+g[pos[i-1][0]][pos[i][0]]);
    }
    else{
        ans1=p[i]*(dfs(i+1,j+1,1)+p[i-1]*(g[pos[i-1][1]][pos[i][1]])+(1-p[i-1])*(g[pos[i-1][0]][pos[i][1]]))+
             (1-p[i])*(dfs(i+1,j+1,1)+p[i-1]*(g[pos[i-1][1]][pos[i][0]])+(1-p[i-1])*(g[pos[i-1][0]][pos[i][0]]));
    }
    return x=min(ans1,ans0);
}
int main(){
    cin>>n>>m>>v>>e;
    int i;
    for(i=1;i<=n;i++)
        cin>>pos[i][0];
    for(i=1;i<=n;i++)
        cin>>pos[i][1];
    for(i=1;i<=n;i++)
        cin>>p[i];
    memset(g,1,sizeof g);
    for(i=1;i<=e;i++){
        int a,b,w;
        cin>>a>>b>>w;
        g[a][b]=g[b][a]=min(w,g[a][b]);
    }
    floyd();
    for(i=1;i<=n;i++){
        for(int j=0;j<=m;j++){
            f[i][j][0]=f[i][j][1]=-1;
        }
    }
    double ans=dfs(1,0,0);
    printf("%.2f
",ans);
    return 0;
}
View Code
没有人不辛苦,只有人不喊疼
原文地址:https://www.cnblogs.com/ctyakwf/p/12713708.html