UvaLive 6441 Horrible Quiz(dp)

题目链接

UvaLive 6441 Horrible Quiz

题意:有n个题目,现在A要一个一个的做,告诉你A做对第i题概率ci,做错的概率wi,还有1-ci-wi的概率他完全没有想法。初始的时候A有15000的积分,如果他答对一道题积分不变,答错一道题积分乘以-1(对就是这么扯淡)。如果一道题他完全没有想法他会去问B怎么做,B知道所有题的正解,但是B可能告诉A正解也可能告诉他错误的答案,还有个限制B最多只能给A说M次错误答案。问A最后积分的期望值中最低的为多少?

A最后得分的期望值其实掌握在B手里,而B会有很多种可行的策略,容易想到用动态规划求解。

dp【i】【j】表示前i个题目,B告诉了A j 次错误的答案,A积分的期望最小值。那么转移就是dp【i】【j】=min(dp【i-1】【j】*(1-2*wi),dp【i-1】【j-1】*(2*ci-1))。

但是这个转移方程是有问题的,因为1-2*wi和2*ci-1的正负不确定,所以我们还要开一维状态,dp【i】【j】【0】表示当前状态的最小值,dp【i】【j】【1】表示当前状态的最大值。那么转移的时候根据(1-2*wi)和(2*ci-1)的正负在前面转移的基础做一些修改就行了。代码如下:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define INFF 1e20
double dp[1300][1300][2];
double c[1300];
double w[1300];
double Min(double x,double y)
{
    return x<y?x:y;
}
double Max(double x,double y)
{
    return x>y?x:y;
}
int main()
{
    int T,ncase=0;
    scanf("%d",&T);
    int i,j;
    int n,m;
    while(T--)
    {
        scanf("%d %d",&n,&m);
        for(i=0;i<=n;i++)
            for(j=0;j<=m;j++)
            {
                dp[i][j][1]=-INFF;
                dp[i][j][0]=INFF;
            }
        for(i=1;i<=n;i++)
        {
            scanf("%lf",&c[i]);
            c[i]=c[i]/100.0;
        }
        for(i=1;i<=n;i++)
        {
            scanf("%lf",&w[i]);
            w[i]=w[i]/100.0;
        }
        dp[0][0][0]=15000.0;
        dp[0][0][1]=15000.0;
        for(i=1;i<=n;i++)
        {
            for(j=0;j<=i&&j<=m;j++)
            {
                if(dp[i-1][j][0]!=INFF)
                {
                    dp[i][j][0]=Min(dp[i][j][0],dp[i-1][j][0]*(1.0-w[i])-dp[i-1][j][0]*w[i]);
                    dp[i][j][1]=Max(dp[i][j][1],dp[i-1][j][0]*(1.0-w[i])-dp[i-1][j][0]*w[i]);
                }
                if(dp[i-1][j][1]!=-INFF)
                {
                    dp[i][j][1]=Max(dp[i][j][1],dp[i-1][j][1]*(1.0-w[i])-dp[i-1][j][1]*w[i]);
                    dp[i][j][0]=Min(dp[i][j][0],dp[i-1][j][1]*(1.0-w[i])-dp[i-1][j][1]*w[i]);
                }
                if(j>0)
                {
                    if(dp[i-1][j-1][0]!=INFF)
                    {
                        dp[i][j][1]=Max(dp[i][j][1],dp[i-1][j-1][0]*c[i]-dp[i-1][j-1][0]*(1.0-c[i]));
                        dp[i][j][0]=Min(dp[i][j][0],dp[i-1][j-1][0]*c[i]-dp[i-1][j-1][0]*(1.0-c[i]));
                    }
                    if(dp[i-1][j-1][1]!=-INFF)
                    {
                        dp[i][j][1]=Max(dp[i][j][1],dp[i-1][j-1][1]*c[i]-dp[i-1][j-1][1]*(1.0-c[i]));
                        dp[i][j][0]=Min(dp[i][j][0],dp[i-1][j-1][1]*c[i]-dp[i-1][j-1][1]*(1.0-c[i]));
                    }
                    //dp[i][j]=Min(dp[i][j],dp[i-1][j-1]*(1-w[i])-dp[i-1][j-1]*w[i]);
                }

               // printf("%lf  ..   ",dp[i][j][0]);
            }
            printf("\n");
        }
        double ans=INFF;
        for(i=0;i<=m;i++)
            ans=Min(ans,dp[n][i][0]);
        printf("Case #%d: %.3lf\n",++ncase,ans);
    }
    return 0;
}


你可能感兴趣的:(dp,动态规划,ACM)