zoukankan      html  css  js  c++  java
  • zoj 3022 Watashi and Kimi

    http://acm.hust.edu.cn:8080/judge/contest/view.action?cid=11975#problem/I

    一道概率题。还是递推题。

    用dp[pre][i][j]表示当前有i道正确的题,j道不正确的题。

    用dp[now][i][j]表示下一个状态有i道正确的题,j道不正确的题。

    如果当前是w同学,那么他有两种选择。

    改错一道题,或者不做任何改变。

    要是改错的话,他只能从对的里面选一道。如果要是不动的话那么他将会从错的题里面选择,而且选择的错的题不能是之前改过的。所以状态如下

    if(i>0)
    dp[now][i-1][j+1]+=dp[pre][i][j]*i/(n-stepw);
    dp[now][i][j]+=dp[pre][i][j]*(j-stepw)/(n-stepw);
    }

    同理k同学的道理是一样的

    if(j>0)
    dp[now][i+1][j-1]+=dp[pre][i][j]*j/(n-stepk);
    dp[now][i][j]+=dp[pre][i][j]*(i-stepk)/(n-stepk);

    如果之前k同学或者w同学已经连续改了n题,那么要跳出,没题目让他改了。跳出后,因为下个状态还没有算出。这时没有下一个状态和上一个状态没有任何改变,所以直接复制

    (尼玛我们memcpy写成memcmp,结果wa的要死。。。)

    用的是滚动数组。

    pre和now是两把指针。

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<string>
    #include<algorithm>
    using namespace std;
    double dp[2][20][20];
    int pre,now;
    int n;
    double solve()
    {
        //cout<<"^^^^"<<endl;
        pre=0;
        now=1;
        //dp[pre][n][0]=1;
        char who[20];
        int stepw=0;
        int stepk=0;
        int i,j;
        memset(dp,0,sizeof(dp));
        dp[pre][n][0]=1;
        while(cin>>who)
        {
            //cout<<who<<"@@@@"<<endl;
            if(who[0]=='E')break;
            else
            for( i=0;i<=n;i++)
            {
                 j=n-i;
                if(who[0]=='W')
                {
                    if(stepw>=n)break;
                    if(i>0)
                    dp[now][i-1][j+1]+=dp[pre][i][j]*i/(n-stepw);//还有正确的题目就该,从正确的里面选
                    dp[now][i][j]+=dp[pre][i][j]*(j-stepw)/(n-stepw);//不动,从错误的里面选。不能选之前的
                }
                else
                if(who[0]=='K')
                {
                    if(stepk>=n)break;
                    if(j>0)
                    dp[now][i+1][j-1]+=dp[pre][i][j]*j/(n-stepk);//还有错误的题目就该,从正确的里面选
                    dp[now][i][j]+=dp[pre][i][j]*(i-stepk)/(n-stepk);//不动,从正确的里面选。不能选之前的
                }
               /* for(int l=0;l<2;l++)
                {
                    for(int k=0;k<=n;k++)
                    {
    
                        for(int o=0;o<=n;o++)
                        cout<<dp[l][k][o]<<" ";
                        cout<<endl;
                    }
                    cout<<endl;
                }*/
            }
            if(i!=n+1)
                memcpy(dp[now],dp[pre],sizeof(dp[0]));//是memcpy啊不是memcmp
            if(who[0]=='W')
                stepw++,stepk=0;
            else
            if(who[0]=='K')
                stepk++,stepw=0;
            swap(pre,now);//交换指针
            memset(dp[now],0,sizeof(dp[now]));
        }
        return dp[pre][n][0];
    }
    
    int main()
    {
        while(cin>>n)
        {
            getchar();
            printf("%.2lf\n",solve());
        }
        return 0;
    }
    

      

  • 相关阅读:
    DNS正向反向解析
    varnish-4.0.5的反向代理 缓存测试 负载均衡实验
    DS8700 硬盘更换略
    ftp虚拟用户
    maven mvn 命令行 编译打包
    linux下的springboot项目启动文件
    linux系统安装gcc
    linux系统下安装两个或多个tomcat
    linux系统的磁盘挂载
    常用linux命令
  • 原文地址:https://www.cnblogs.com/cs1003/p/2653515.html
Copyright © 2011-2022 走看看