UvaLive 6441 Horrible Quiz 贪心

链接:http://vjudge.net/problem/viewProblem.action?id=47588

题意:刚开始有15000的积分,有N道题,对于每道题,有Ci%的概率答对,有Wi%的概率答错,(100-Ci-Wi)%的概率会选择提供的答案,可以提供的答案中最多可以提供M个错的答案,剩下的都必须是对的,答错的时候,积分*-1,答对的时候积分不变,问可以选择的M题,使可以得到的分数最低的期望是多少。

思路:公式中Ci,Wi分别表示正确和错误的概率(Ci+Wi=1)

对于提供错误答案和正确答案的情况下答对题的概率是不同的,所以分别记录。 因为要使期望尽可能的小,所以最优的情况是尽可能使积分是负数,并且是期望的绝对值尽可能大,如果期望不能是负数,那么就要使积分的绝对值尽可能小。根据提供错误答案与提供正确答案获得的期望之比来进行决定提供错误答案的题和提供正确答案的题,即可获得最优解。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define eps 1e-8
using namespace std;
struct point
{
    int a,b;
    double ac,wa;
} aa[1255],zz[1255],ff[1255],cc[1255];
bool cmp1(point a,point b)
{
    return fabs(a.wa*b.ac)<fabs(b.wa*a.ac);
}
bool cmp2(point a,point b)
{
    return fabs(a.wa*b.ac)>fabs(b.wa*a.ac);
}
int main()
{
    int T;
    scanf("%d",&T);
    for(int ii=1; ii<=T; ii++)
    {
        double ans=15000;
        int tw=0,tt=0,tb0=0;
        int tot,wrong,top1=0;
        scanf("%d%d",&tot,&wrong);
        for(int i=0; i<tot; i++)
            scanf("%d",&aa[i].a);
        for(int i=0; i<tot; i++)
            scanf("%d",&aa[i].b);
        printf("Case #%d: ",ii);
        for(int i=0; i<tot; i++)
        {
            aa[i].ac=(double)((100-aa[i].b)*2-100);
            aa[i].ac/=100.0;
            aa[i].wa=(double)(aa[i].a*2-100);
            aa[i].wa/=100.0;
            if(aa[i].ac<0)
            {
                tw++;
                ff[top1++]=aa[i];
            }
            else if(aa[i].wa>=0)
            {
                ff[top1++]=aa[i];
            }
            else
            {
                cc[tt++]=aa[i];
            }
            if(aa[i].ac==0)
                tb0++;
            if(aa[i].wa==0)
                tb0++;
        }
        if(wrong==0)
        {
            for(int i=0; i<tot; i++)
            {
                ans*=aa[i].ac;
            }
            if (fabs(ans)<eps)
                ans=0;
            printf("%.4f\n",ans);
        }
        else if(tw%2==0&&tt==0)
        {
            if(tb0)
                printf("0.000\n");
            else
            {
                sort(ff,ff+top1,cmp1);
                for(int i=0; i<wrong; i++)
                {
                    if(fabs(ff[i].wa)<fabs(ff[i].ac))
                        ans*=fabs(ff[i].wa);
                    else
                    {
                        ans*=fabs(ff[i].ac);
                    }
                }
                for(int j=wrong; j<tot; j++)
                    ans*=fabs(ff[j].ac);
                if (fabs(ans)<eps)
                    ans=0;
                printf("%.4f\n",ans);
            }
        }
        else
        {
            int ttw=0,ttc=0;
            if(tw%2==0&&tt!=0)
            {
                wrong--;
            ttw++;
            }
            sort(cc,cc+tt,cmp2);
            sort(ff,ff+top1,cmp2);
            while(wrong)
            {
                if(wrong>=2&&tt-ttw>=2)
                {
                    if(ttc<top1)
                    {
                        if(cc[ttw].wa/cc[ttw].ac*cc[ttw+1].wa/cc[ttw+1].ac>=ff[ttc].wa/ff[ttc].ac&&cc[ttw].wa/cc[ttw].ac*cc[ttw+1].wa/cc[ttw+1].ac>1)
                        {
                            wrong-=2;
                            ttw+=2;
                        }
                        else if(cc[ttw].wa/cc[ttw].ac*cc[ttw+1].wa/cc[ttw+1].ac<ff[ttc].wa/ff[ttc].ac&&ff[ttc].wa/ff[ttc].ac>1)
                        {
                            wrong--;
                            ttc++;
                        }
                        else break;
                    }
                    else
                    {
                        if(cc[ttw].wa/cc[ttw].ac*cc[ttw+1].wa/cc[ttw+1].ac>1)
                        {
                            wrong-=2;
                            ttw+=2;
                        }
                        else break;
                    }
                }
                else if(wrong>=1)
                {
                    if(ttc<top1&&ff[ttc].wa/ff[ttc].ac>1)
                    {
                        wrong--;
                        ttc++;
                    }
                    else break;
                }
            }
            for(int i=0; i<ttw; i++)
                ans*=cc[i].wa;
            for(int i=ttw; i<tt; i++)
                ans*=cc[i].ac;
            for(int i=0; i<ttc; i++)
                ans*=ff[i].wa;
            for(int i=ttc; i<top1; i++)
                ans*=ff[i].ac;
            if (fabs(ans)<eps)
                ans=0;
            printf("%.4f\n",ans);
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值