【NOIP2016提高组复赛】换教室

Description

【NOIP2016提高组复赛】换教室_第1张图片

Solution

这题正解很短很简单,就是基础的概率期望题。
比赛的时候打floyd暴力可以过80分。
先用floyd预处理一下。
设f[i][j][k]表示第i个时间段,选了j个教室要申请(不一定成功),k表示i申请或不申请。
我们从i推到i+1,如果要推到f[i+1][j][0]的话,那么第i+1个时间段肯定在a[i+1]。这个可以从i的0状态和1状态推过来,如果从0推过来,那么i时间段肯定在a[i]这个地方,那么期望是d[a[i]][a[i+1]],概率是1。如果从1推过来,那么i有两种情况,申请成功和申请不成功,所以i时间段可能在a[i]或b[i],概率为1-gai[i]和gai[i]。
所以 f[i+1][j][0]=min(f[i][j][0]+d[a[i]][a[i+1]],f[i][j][1]+(1gai[i])d[a[i]][a[i+1]]+gai[i]d[b[i]][a[i+1]]);
要推倒f[i+1][j][1]情况类似,不过要考虑i+1申请成不成功的情况。
如果(j!=m)
f[i+1][j+1][1]=min(f[i][j][0]+d[a[i]][b[i+1]]gai[i+1]+d[a[i]][a[i+1]](1gai[i+1])
否则
f[i][j][1]+d[a[i]][a[i+1]](1gai[i])(1gai[i+1])+d[b[i]][a[i+1]]gai[i](1gai[i+1])+d[a[i]][b[i+1]](1gai[i])gai[i+1]+d[b[i]][b[i+1]]gai[i]gai[i+1]);
最后答案就是min(f[n][j][0,1])

Code

#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
#define rep(i,a) for(i=first[a];i;i=next[i])
using namespace std;
typedef long long ll;
const int maxn=2007,mo=1e9+7;
int i,j,k,l,t,n,m,v,e;
int a[maxn],b[maxn];
double gai[maxn];
int first[maxn*2],last[maxn*2],next[maxn*2],chang[maxn*2],num,ber;
double f[maxn][maxn][2];
int d[maxn][maxn];
bool bz[maxn];
double ans,ans1;
int cnt,cnt1;
void add(int x,int y,int z){
    last[++num]=y,next[num]=first[x],first[x]=num;chang[num]=z;
}
int main(){
    freopen("classroom.in","r",stdin);
    freopen("classroom.out","w",stdout);
   // freopen("fan.in","r",stdin);
    scanf("%d%d%d%d",&n,&m,&v,&e);
    fo(i,1,n)scanf("%d",&a[i]);
    fo(i,1,n)scanf("%d",&b[i]);
    fo(i,1,n)scanf("%lf",&gai[i]);
    memset(d,127/2,sizeof(d));
    fo(i,1,e){
        scanf("%d%d%d",&k,&l,&t);
        add(k,l,t);add(l,k,t);
        d[k][l]=min(d[k][l],t);
        d[l][k]=min(d[l][k],t);
    }
    fo(i,1,v)d[i][i]=0;
    fo(k,1,v)fo(i,1,v)fo(j,1,v)if(d[i][k]+d[k][j]1,v)d[0][i]=0;
    fo(i,0,2006)fo(j,0,2006)fo(k,0,1)f[i][j][k]=99999999999;
    f[0][0][0]=0;
    fo(i,0,n-1){
        fo(j,0,m){
            f[i+1][j][0]=min(f[i][j][0]+d[a[i]][a[i+1]],f[i][j][1]+(1-gai[i])*d[a[i]][a[i+1]]+gai[i]*d[b[i]][a[i+1]]);
            if(j!=m)f[i+1][j+1][1]=min(f[i][j][0]+d[a[i]][b[i+1]]*gai[i+1]+d[a[i]][a[i+1]]*(1-gai[i+1]),
            f[i][j][1]+d[a[i]][a[i+1]]*(1-gai[i])*(1-gai[i+1])+d[b[i]][a[i+1]]*gai[i]*(1-gai[i+1])+d[a[i]][b[i+1]]*(1-gai[i])*gai[i+1]+d[b[i]][b[i+1]]*gai[i]*gai[i+1]);
        }
    }
    ans=99999999999;
    fo(j,0,m)ans=min(ans,min(f[n][j][0],f[n][j][1]));
    printf("%.2lf\n",ans);
    return 0;
}

你可能感兴趣的:(noip,概率,DP)