http://acm.hdu.edu.cn/showproblem.php?pid=4923
Room and Moor
Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1105 Accepted Submission(s): 352
Problem Description
PM Room defines a sequence A = {A
1, A
2,..., A
N}, each of which is either 0 or 1. In order to beat him, programmer Moor has to construct another sequence B = {B
1, B
2,... , B
N} of the same length, which satisfies that:
Input
The input consists of multiple test cases. The number of test cases T(T<=100) occurs in the first line of input.
For each test case:
The first line contains a single integer N (1<=N<=100000), which denotes the length of A and B.
The second line consists of N integers, where the ith denotes A i.
For each test case:
The first line contains a single integer N (1<=N<=100000), which denotes the length of A and B.
The second line consists of N integers, where the ith denotes A i.
Output
Output the minimal f (A, B) when B is optimal and round it to 6 decimals.
Sample Input
4 9 1 1 1 1 1 0 0 1 1 9 1 1 0 0 1 1 1 1 1 4 0 0 1 1 4 0 1 1 1
Sample Output
1.428571 1.000000 0.000000 0.000000
贪心,从后往前找平均值最大的序列,使平均值按递增排列,计算一下方差即可。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn=110000;
int a[maxn];
int main()
{
int n,t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int maxi,coun0,coun,coun1,count0,count1,signn;
double max,te,ans;
signn=n-1;
ans=0.0;
while(1)
{
te=0.0;
max=0.0;
maxi=signn;
coun0=coun1=count1=count0=coun=0;
for(int i=signn;i>=0;i--)//从未被计算的向前找最大值(也可以向后找最小值)
{
coun++;
if(a[i]==0)
{
coun0++;
}
else
{
coun1++;
}
te=coun1*1.0/coun;
if(te>=max)
{
max=te;
maxi=i;
count0=coun0;
count1=coun1;
}
}
ans+=((1.0-max)*(1.0-max)*count1+max*max*count0);//计算找到的这一段的方差
signn=maxi-1;//标记已被处理过的位置
if(signn==-1)//当全部被处理
break;
}
printf("%.6f\n",ans);
}
return 0;
}