The secret code

The secret code

Input file: stdinOutput file: stTime limit: 1 sec

Memory limit: 256 Mb
After returning from the trip, Alex was unpleasantly surprised: his porch door had a new combination lock. Alex
can not get into his house! Code lock contains N disks, each of which can be in one of M positions. There
is only one correct position. Alex thoroughly inspected discs and by fingerprints and scratches determined the
probability of each position for each disk. Now Alex has K attempts to guess the correct code: if he fails, his
vigilant neighbors will call the police, and Alex will have a hard time persuading cops that he is not a thief, but
tried to get home. Help Alex to calculate the maximum probability of getting home, not to the police.
Limit
1 ≤ N ≤ 100
1 ≤ M ≤ 20
1 ≤ K ≤ 100
0 ≤ P ij ≤ 100
Input
The first line of input file contains three integers: N, M Рё K.
Next N lines contain M integers each: j-th number of the i-th line (P ij ) — the probability of a situation where
i-th disc’s correct position is j. Given that
P M
j=1 P ij
= 100.
Output
Print a single number — Alex’s chances to guess the correct code in time. Output result should have an absolute
percentage error not grater than 10 −7 .
Example
stdin

2 2 1
50 50
10 90
3 5 4
10 15 20 25 30
1 2 3 4 90
100 0 0 0 0

stdout

0.45
0.81

题目大意:

   n个数列,每个数列取一个数,得到这些数的乘积,求前k个最大的乘积。

多谢syx的指导!

解题思路:

  对每个数列排序后。

  首先,第一大的自然是所有数列最大值乘积。

  接着,将最大乘积加到ans上,然后将这个乘积能够达到的所有下一个状态均加入优先队列中。至于保存状态,每个状态只需保存其在每个数列的取到第几个数的指针即可,显然下一个状态是在该状态之后,并且出现在某一个指针向后移位。故将所有下一个状态加入优先队列。

  然后,当找到第k个或者是空队列时退出循环,否则返回上一步。

  最后,输出答案。

实现方法,直接使用STL中的priority_queue,若数据量加大,可惜优先队列不能删除尾节点,不过可利用最大最小堆保存前k个即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
#include <stack>
#include <queue>
#include <map>
#include <deque>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))

using namespace std;

struct State{
    int head[105];
    double x;
    bool operator<(const State &b) const
    {
        return x<b.x;
    }
};

double a[105][21];
int n,m,k;
priority_queue<State> q;
bool cmp(double x, double y)
{
    return x>y;
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<m; j++)
        {
            scanf("%lf",&a[i][j]);
            a[i][j]/=100;
        }
        sort(a[i],a[i]+m,cmp);
    }

    State tmp;
    tmp.x=1.0;
    for(int i=0; i<n; i++)
    {
        tmp.head[i]=0;
        tmp.x*=a[i][0];
    }
    q.push(tmp);

    double ans=0.0;
    for(int i=0; i<k&&!q.empty(); i++)
    {
        tmp=q.top();
        q.pop();
        ans+=tmp.x;
        for(int j=0; j<n; j++)
            if(tmp.head[j]<m-1) 
            {
                if(a[j][tmp.head[j]+1]==0) continue;
                tmp.x=tmp.x / a[j][tmp.head[j]] * a[j][tmp.head[j]+1];
                tmp.head[j]++;
                q.push(tmp);
                tmp.x=tmp.x / a[j][tmp.head[j]] * a[j][tmp.head[j]-1];
                tmp.head[j]--;
            }
    }

    printf("%.8f
",ans);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Mathics/p/3906139.html