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;
}

  

原文地址:https://www.cnblogs.com/cs1003/p/2653515.html