鏈接: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;
}