Nordic Collegiate Programming Contest 2017 题解

前几天打了一场外国人的比赛,感觉那边的题目质量还是很好的,区分度很鲜明,题目没有国内的难,坑点比较少,比较注重思维,基础算法。


B题:

Best Relay Team

Nordic Collegiate Programming Contest 2017 题解_第1张图片
Picture by Fernando Frazão/Agência Brasil, cc by
You are the coach of the national athletics team and need to select which sprinters should represent your country in the  4×100 4×100 m relay in the upcoming championships.

As the name of the event implies, such a sprint relay consist of  4 4legs,  100 100 meters each. One would think that the best team would simply consist of the  4 4 fastest  100 100 m runners in the nation, but there is an important detail to take into account: flying start. In the  2 2nd,  3 3rd and  4 4th leg, the runner is already running when the baton is handed over. This means that some runners – those that have a slow acceleration phase – can perform relatively better in a relay if they are on the  2 2nd,  3 3rd or  4 4th leg.

You have a pool of runners to choose from. Given how fast each runner in the pool is, decide which four runners should represent your national team and which leg they should run. You are given two times for each runner – the time the runner would run the  1 1st leg, and the time the runner would run any of the other legs. A runner in a team can only run one leg.

Input

The first line of input contains an integer  n n, the number of runners to choose from ( 4n500 4≤n≤500). Then follow  n n lines describing the runners. The  i i’th of these lines contains the name of the  i i’th runner, the time  ai ai for the runner to run the  1 1st leg, and the time  bi bi for the runner to run any of the other legs ( 8biai<20 8≤bi≤ai<20). The names consist of between  2 2 and  20 20 (inclusive) uppercase letters ‘A’-‘Z’, and no two runners have the same name. The times are given in seconds with exactly two digits after the decimal point.

Output

First, output a line containing the time of the best team, accurate to an absolute or relative error of at most  109 10−9. Then output four lines containing the names of the runners in that team. The first of these lines should contain the runner you have picked for the  1 1st leg, the second line the runner you have picked for the  2 2nd leg, and so on. Any solution that results in the fastest team is acceptable.

Sample Input 1 Sample Output 1
6
ASHMEADE 9.90 8.85
BLAKE 9.69 8.72
BOLT 9.58 8.43
CARTER 9.78 8.93
FRATER 9.88 8.92
POWELL 9.72 8.61
35.54
CARTER
BOLT
POWELL
BLAKE
Sample Input 2 Sample Output 2
9
AUSTRIN 15.60 14.92
DRANGE 15.14 14.19
DREGI 15.00 14.99
LAAKSONEN 16.39 14.97
LUNDSTROM 15.83 15.35
MARDELL 13.36 13.20
POLACEK 13.05 12.55
SANNEMO 15.23 14.74
SODERMAN 13.99 12.57
52.670000
MARDELL
POLACEK
SODERMAN
DRANGE
这个题是签到题,比较简单,枚举第一个人,后面三个人取最快的三个人就行

#include 
using namespace std;
const int maxn = 500 + 10;
int n;
double eps = 0.0000000001;
struct node{
    string name;
    double speed1, speed2;
    bool operator <(const node &res) const{
        return speed2 < res.speed2;
    }
}Node[maxn];
vector g;
int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        cin>>Node[i].name>>Node[i].speed1>>Node[i].speed2;
    }
    double Min = 1000000000000.0;
    string s1, s2, s3, s4;
    for(int i = 1; i <= n; i++)
    {
        g.clear();
        double sum = Node[i].speed1;
        for(int j = 1; j <= n; j++)
        {
            if(j != i) g.push_back(Node[j]);
        }
        sort(g.begin(), g.end());
        for(int j = 0; j <= 2; j++)
        {
            sum += g[j].speed2;
        }
        if(sum - Min < eps)
        {
            Min = sum;
            s1 = Node[i].name;
            s2 = g[0].name;
            s3 = g[1].name;
            s4 = g[2].name;
        }

    }
    printf("%.2lf\n", Min);
    cout<

D题:

Distinctive Character

Nordic Collegiate Programming Contest 2017 题解_第2张图片
Picture by Fairytalemaker on Pixabay
Tira would like to join a multiplayer game with  n n other players. Each player has a character with some features. There are a total of  k k features, and each character has some subset of them.

The similarity between two characters  A A and  B B is calculated as follows: for each feature  f f, if both  A A and  B B have feature  f for if none of them have feature  f f, the similarity increases by one.

Tira does not have a character yet. She would like to create a new, very original character so that the maximum similarity between Tira’s character and any other character is as low as possible.

Given the characters of the other players, your task is to create a character for Tira that fulfils the above requirement. If there are many possible characters, you can choose any of them.

Input

The first line of input contains two integers  n n and  k k, where  1n105 1≤n≤105 is the number of players (excluding Tira) and  1k20 1≤k≤20 is the number of features.

Then follow  n n lines describing the existing characters. Each of these  n n lines contains a string of  k k digits which are either  0 0 or  1 1. A  1 1 in position  j j means the character has the  j j’th feature, and a  0 0 means that it does not have the  j j’th feature.

Output

Output a single line describing the features of Tira’s character in the same format as in the input. If there are multiple possible characters with the same smallest maximum similarity, any one of them will be accepted.

Sample Input 1 Sample Output 1
3 5
01001
11100
10111
00010
Sample Input 2 Sample Output 2
1 4
0000
1111
这个题很有意思,一共有2的k次方种串,显然枚举每一种串,时间复杂度为O(n * 2^k),不能接受,好像也dp不了,我们把2^k种状态都当成一个点,每个点与它代表的串中只有一位不相同,其他位都相同的点相连,所以每个点与k个点相连,然后问题就转换为,在一些点中找出一个点,使得这个点与给定点的集合的距离的最小值最大,那么我们建立一个超级源点,与给定集合的每个点相连,距离为0,然后用最短路求出每个点到超级源点的最短距离就行,最后,找出最大的那个距离就行。

#include 
using namespace std;
const int maxn = 1000000 + 200000;
int inf = 0x3f3f3f3f;
int n, tot, k;
int head[maxn];
bool visit[maxn];
char ch[30];
int digit[30];
int dis[maxn];
int sum;
struct edge{
    int v, w, Nxt;
}Edge[maxn<<5];
vector g;
void init()
{
    tot = 0;
    memset(head, -1, sizeof(head));
    memset(visit, false, sizeof(visit));
    g.clear();
}
int Transform(char *s)
{
    int ans = 0;
    int len = strlen(s);
    for(int i = 0; i < len; i++)
    {
        if(s[i] == '1') ans += (1<>i)&1;
    }
    for(int i = 0; i < k; i++)
    {
        int x = 0;
        for(int j = 0; j < k; j++)
        {
            int value;
            if(i == j) value = digit[j]^1;
            else value = digit[j];
            if(value) x += (1< res.w;
    }
};
void bfs()
{
    memset(dis, inf, sizeof(dis));
    priority_queue q;
    while(!q.empty()) q.pop();
    q.push(node(sum, 0));
    dis[sum] = 0;
    while(!q.empty())
    {
        node nx = q.top();
        q.pop();
        int u = nx.u;
        int w = nx.w;
        if(dis[u] < w) continue;
        for(int i = head[u]; i != -1; i = Edge[i].Nxt)
        {

            int v = Edge[i].v;
            int ww = Edge[i].w;
            if(dis[v] > dis[u] + ww)
            {
                dis[v] = dis[u] + ww;
                q.push(node(v, dis[v]));
            }
        }
    }
}
int main()
{
    init();
    scanf("%d%d", &n, &k);
    int judge = 0;
    for(int i = 1; i <= n; i++)
    {
        scanf("%s", ch);
        int num = Transform(ch);
        if(!visit[num])
        {
            visit[num] = true;
            g.push_back(num);
            judge++;
        }
    }
    sum = (1<= sum)
    {
        for(int i = 1; i <= k; i++)
        {
            cout<<"0";
        }
        cout< Max)
        {
            Max = dis[i];
            st = i;
        }
    }
    for(int i = 0; i < k; i++)
    {
        int value = (st>>i)&1;
        cout<
 
  
E题:


Emptying the Baltic

Nordic Collegiate Programming Contest 2017 题解_第3张图片
Picture by Jeremy Halls on Flickr, cc by-sa
Gunnar dislikes forces of nature and always comes up with innovative plans to decrease their influence over him. Even though his previous plan of a giant dome over Stockholm to protect from too much sunlight (as well as rain and snow) has not yet been realized, he is now focusing on preempting the possible effects climate change might have on the Baltic Sea, by the elegant solution of simply removing the Baltic from the equation.

First, Gunnar wants to build a floodbank connecting Denmark and Norway to separate the Baltic from the Atlantic Ocean. The floodbank will also help protect Nordic countries from rising sea levels in the ocean. Next, Gunnar installs a device that can drain the Baltic from the seafloor. The device will drain as much water as needed to the Earth’s core where it will disappear forever (because that is how physics works, at least as far as Gunnar is concerned). However, depending on the placement of the device, the entire Baltic might not be completely drained – some pockets of water may remain.

To simplify the problem, Gunnar is approximating the map of the Baltic using a  2 2-dimensional grid with  1 1meter squares. For each square on the grid, he computes the average altitude. Squares with negative altitude are covered by water, squares with non-negative altitude are dry. Altitude is given in meters above the sea level, so the sea level has altitude of exactly  0 0. He disregards lakes and dry land below the sea level, as these would not change the estimate much anyway.

Water from a square on the grid can flow to any of its  8 8 neighbours, even if the two squares only share a corner. The map is surrounded by dry land, so water never flows outside of the map. Water respects gravity, so it can only flow closer to the Earth’s core – either via the drainage device or to a neighbouring square with a lower water level.

Gunnar is more of an idea person than a programmer, so he has asked for your help to evaluate how much water would be drained for a given placement of the device.

Input

The first line contains two integers  h h and  w w 1h,w500 1≤h,w≤500, denoting the height and width of the map.

Then follow  h h lines, each containing  w w integers. The first line represents the northernmost row of Gunnar’s map. Each integer represents the altitude of a square on the map grid. The altitude is given in meters and it is at least  106 −106 and at most  106 106.

The last line contains two integers  i i and  j j 1ih,1jw 1≤i≤h,1≤j≤w, indicating that the draining device is placed in the cell corresponding to the  j j’th column of the  i i’th row. You may assume that position  (i,j) (i,j) has negative altitude (i.e., the draining device is not placed on land).

Output

Output one line with one integer – the total volume of sea water drained, in cubic meters.

Sample Input 1 Sample Output 1
3 3
-5 2 -5
-1 -2 -1
5 4 -5
2 2
10
Sample Input 2 Sample Output 2
2 3
-2 -3 -4
-3 -2 -3
2 1
16
刚开始用dfs,然后一直tle,最后发现可以不用dfs,每个点维护一个最大能流走的值就行,我们从有抽水机的地方开始更新,类似于迪杰斯塔拉最短路的过程,每次取出最大的那个,然后对它周围的点进行更新就行。

#include 
using namespace std;
typedef long long LL;
const int maxn = 510;
int h, w, s, t;
LL M[maxn][maxn];
LL Level[maxn][maxn];
LL dis[maxn][maxn];
int dx[4] = {0, 1, -1};
int dy[4] = {0, 1, -1};
LL up;
bool visit[maxn][maxn];
bool judge(int xx, int yy)
{
    if(xx < 1 || xx > h) return false;
    if(yy < 1 || yy > w) return false;
    return true;
}
struct node{
    int x, y;
    LL d;
    node(){}
    node(int _x, int _y, LL _d){
        x = _x;
        y = _y;
        d = _d;
    }
    bool operator <(const node &res) const {
        return d < res.d;
    }
};
LL ans;
void solve()
{
    priority_queue q;
    while(!q.empty()) q.pop();
    q.push(node(s, t, -M[s][t]));
    dis[s][t] = -M[s][t];
    up = -M[s][t];
    while(!q.empty())
    {
        node nx = q.top();
        q.pop();
        int x = nx.x;
        int y = nx.y;
        LL d = nx.d;
        if(dis[x][y] > d) continue;
        for(int i = 0; i <= 2; i++)
        {
            for(int j = 0; j <= 2; j++)
            {
                if(i == j && i == 0) continue;
                int nowx = x + dx[i];
                int nowy = y + dy[j];
                if(!judge(nowx, nowy)) continue;
                if(M[nowx][nowy] >= 0) continue;

                LL Max = min(dis[x][y], abs(M[nowx][nowy]));
                Max = min(Max, up);
                if(dis[nowx][nowy] < Max)
                {
                     dis[nowx][nowy] = Max;
                     q.push(node(nowx, nowy, Max));
                }
            }
        }
    }
}
int main()
{
    scanf("%d%d", &h, &w);
    for(int i = 1; i <= h; i++)
    {
        for(int j = 1; j <= w; j++)
        {
            scanf("%lld", &M[i][j]);
        }
    }
    scanf("%d%d", &s, &t);
    memset(visit, false, sizeof(visit));
    memset(dis, 0, sizeof(dis));
    ans = 0;
    solve();
    for(int i = 1; i <= h; i++)
    {
        for(int j = 1; j <= w; j++)
        {
            ans += dis[i][j];
        }
    }

    printf("%lld\n", ans);
    return 0;
}

G题:

Galactic Collegiate Programming Contest

Nordic Collegiate Programming Contest 2017 题解_第4张图片
Picture by GuillaumePreat on Pixabay, cc0
One hundred years from now, in  2117 2117, the International Collegiate Programming Contest (of which the NCPC is a part) has expanded significantly and it is now the Galactic Collegiate Programming Contest (GCPC).

This year there are  n n teams in the contest. The teams are numbered  1,2,,n 1,2,…,n, and your favorite team has number  1 1.

Like today, the score of a team is a pair of integers  (a,b) (a,b)where  a a is the number of solved problems and  b b is the total penalty of that team. When a team solves a problem there is some associated penalty (not necessarily calculated in the same way as in the NCPC – the precise details are not important in this problem). The total penalty of a team is the sum of the penalties for the solved problems of the team.

Consider two teams  t1 t1 and  t2 t2 whose scores are  (a1,b1) (a1,b1) and  (a2,b2) (a2,b2). The score of team  t1 t1 is better than that of  t2 t2if either  a1>a2 a1>a2, or if  a1=a2 a1=a2 and  b1<b2 b1. The rank of a team is  k+1 k+1 where  k k is the number of teams whose score is better.

You would like to follow the performance of your favorite team. Unfortunately, the organizers of GCPC do not provide a scoreboard. Instead, they send a message immediately whenever a team solves a problem.

Input

The first line of input contains two integers  n n and  m m, where  1n105 1≤n≤105 is the number of teams, and  1m105 1≤m≤105 is the number of events.

Then follow  m m lines that describe the events. Each line contains two integers  t t and  p p ( 1tn 1≤t≤n and  1p1000 1≤p≤1000), meaning that team  t t has solved a problem with penalty  p p. The events are ordered by the time when they happen.

Output

Output  m m lines. On the  i i’th line, output the rank of your favorite team after the first  i i events have happened.

Sample Input 1 Sample Output 1
3 4
2 7
3 5
1 6
1 9
2
3
2
1
这个题,出的很好,听说正解是用集合搞一搞,我们这里用的树状数组,把这个二维问题转化为一维问题,如果一个队伍解出一题,我们给他加上一个-(1e8 + 1),每个队维护一个这个值得就行,先离线处理出所有可能的数字,然后离散化一下,最后就变成了树状数组求逆序对问题了。

#include 
using namespace std;
typedef long long LL;
const int maxn = 100000 + 10;
int n, m;
LL inf = -(1e8 + 1);
LL H[maxn * 2];
int Tree[maxn<<1];
int cnt;
int lowbit(int x)
{
    return x&(-x);
}
void add(int loc, int value)
{
    for(int i = loc; i <= cnt; i += lowbit(i))
    {
        Tree[i] += value;
    }
}
int get(int loc)
{
    int ans = 0;
    for(int i = loc; i >= 1; i -= lowbit(i))
    {
        ans += Tree[i];
    }
    return ans;
}
int Hash(LL value)
{
    return lower_bound(H, H + cnt, value) - H + 1;
}
void init()
{
    sort(H, H + cnt);
    cnt = unique(H, H + cnt) - H;
    memset(Tree, 0, sizeof(Tree));
}
struct node{
    int team, t;
}Node[maxn];
LL Time[maxn];
int main()
{
    scanf("%d%d", &n, &m);
    memset(Time, 0, sizeof(Time));
    cnt = 0;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d%d", &Node[i].team, &Node[i].t);
        int team = Node[i].team;
        int tt = Node[i].t;
        Time[team] += (inf + tt);
        H[cnt++] = Time[team];
    }
    init();
    memset(Time, 0, sizeof(Time));
    for(int i = 1; i <= m; i++)
    {
        int team = Node[i].team;
        int tt = Node[i].t;
        int before = Hash(Time[team]);
        add(before, -1);
        Time[team] += (inf + tt);
        int now = Hash(Time[team]);
        add(now, 1);
        int loc = Hash(Time[1]);
        printf("%d\n", get(loc - 1) + 1);
    }
    return 0;
}

补上这题集合的代码:

#include 
using namespace std;
const int maxn = 100000 + 10;
int n, m;
int p[maxn], t[maxn];
struct team{
    int pp, tt;
    team(){};
    team(int _pp, int _tt){
        pp = _pp;
        tt = _tt;
    }
    bool operator <(const team &res) const{
        if(pp == res.pp) return tt > res.tt;
        else return pp < res.pp;
    }
    bool operator ==(const team &res) const{
        return (pp == res.pp && tt == res.tt);
    }
};
multiset s;
multiset::iterator it;
int main()
{
    scanf("%d%d", &n, &m);
    s.clear();
    memset(p, 0, sizeof(p));
    memset(t, 0, sizeof(t));
    int id, value;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d%d", &id, &value);
        if(id == 1)
        {
            p[1]++;
            t[1] += value;
            team n1 = team(p[1], t[1]);
            while(!s.empty())
            {
                it = s.begin();
                team nx = *it;
                if(nx < n1 || nx == n1) s.erase(it);
                else break;
            }
        }
        else
        {
            int p1 = p[id] + 1;
            int t1 = t[id] + value;
            team n1 = team(p1, t1);
            team n2 = team(p[1], t[1]);
            if(n2 < n1)
            {
               it = s.find(team(p[id], t[id]));
               if(it != s.end()) s.erase(it);
               p[id]++;
               t[id] += value;
               s.insert(team(p[id], t[id]));
            }
            else
            {
                p[id]++;
                t[id] += value;
            }
        }
        printf("%d\n", s.size() + 1);
    }
    return 0;
}


I题:

Import Spaghetti

Nordic Collegiate Programming Contest 2017 题解_第5张图片
cc-by NCPC 2017
You just graduated from programming school and nailed a Python programming job. The first day at work you realize that you have inherited a mess. The  spaghetti design pattern was chosen by the previous maintainer, who recently fled the country. You try to make sense of the code, but immediately discover that different files depend cyclically on each other. Testing the code, in fact running the code, has not yet been attempted.

As you sit down and think, you decide that the first thing to do is to eliminate the cycles in the dependency graph. So you start by finding a shortest dependency cycle.

Input

The first line of input contains a number  n n 1n500 1≤n≤500, the number of files. Then follows one line with  n ndistinct names of files. Each name is a string with at least  1 1 and at most  8 8 lower case letters ‘a’ to ‘z’. Then follow  n n sections, one section per file name, in the order they were given on the second line. Each section starts with one line containing the name of the file and an integer  k k, followed by  k k lines, each starting with “import”.

Each “import” line is a comma-space separated line of dependencies. No file imports the same file more than once, and every file imported is listed in the second line of the input. Comma-space separated means that every line will start with “import”, then have a list of file names separated by “, ” (see sample inputs for examples). Each import statement is followed by at least one file name.

Output

If the code base has no cyclic dependencies, output “SHIP IT”. Otherwise, output a line containing the names of files in a shortest cycle, in the order of the cycle (i.e., the  i ith file listed must import the  (i+1) (i+1)st file listed, and the last file listed must import the first). If there are many shortest cycles, any one will be accepted.

Sample Input 1 Sample Output 1
4
a b c d
a 1
import d, b, c
b 2
import d
import c
c 1
import c
d 0
c
Sample Input 2 Sample Output 2
5
classa classb myfilec execd libe
classa 2
import classb
import myfilec, libe
classb 1
import execd
myfilec 1
import libe
execd 1
import libe
libe 0
SHIP IT
Sample Input 3 Sample Output 3
5
classa classb myfilec execd libe
classa 2
import classb
import myfilec, libe
classb 1
import execd
myfilec 1
import libe
execd 1
import libe, classa
libe 0
n不是很大,所有我们枚举每一个点为起点,用bfs找一个最小的环就行。

#include 
using namespace std;
const int maxn = 500 + 10;
int n;
map mp;
map mmpp;
vector g[maxn];
bool visit[maxn];
char ch[1000000];
char test[1000000];
struct node{
    int v, depth;
    node(){}
    node(int _v = 0, int _depth = 0){
        v = _v;
        depth = _depth;
    }
};
int pre[maxn];
vector ans;
int bfs(int s)
{
    queue q;
    while(!q.empty()) q.pop();
    memset(visit, false, sizeof(visit));
    memset(pre, -1, sizeof(pre));
    q.push(node(s, 0));
    visit[s] = true;
    while(!q.empty())
    {
        node nx = q.front();
        q.pop();
        int u = nx.v;
        int depth = nx.depth;
        for(int i = 0; i < g[u].size(); i++)
        {
            if(g[u][i] == s)
            {
                pre[s] = u;
                return depth;
            }
            int v = g[u][i];
            if(!visit[v])
            {
                visit[v] = true;
                pre[v] = u;
                q.push(node(v, depth + 1));
            }
        }
    }
    return -1;

}
void debug()
{
    for(int i = 1; i <= n; i++)
    {
        cout<<"i == "<>s;
        mp[s] = i;
        mmpp[i] = s;
        //cout<<"s == "<>s>>num;
        int id = mp[s];
        //cout<<"num == "<= 0; i--)
        {
            if(i == 0) cout<

J题:

Judging Moose

Picture by Ryan Hagerty/US Fish and Wildlife Service, public domain
When determining the age of a bull moose, the number of tines (sharp points), extending from the main antlers, can be used. An older bull moose tends to have more tines than a younger moose. However, just counting the number of tines can be misleading, as a moose can break off the tines, for example when fighting with other moose. Therefore, a point system is used when describing the antlers of a bull moose.

The point system works like this: If the number of tines on the left side and the right side match, the moose is said to have the even sum of the number of points. So, “an even  6 6-point moose”, would have three tines on each side. If the moose has a different number of tines on the left and right side, the moose is said to have twice the highest number of tines, but it is odd. So “an odd  10 10-point moose” would have  5 5 tines on one side, and  4 4 or less tines on the other side.

Can you figure out how many points a moose has, given the number of tines on the left and right side?

Input

The input contains a single line with two integers   and  r r, where  020 0≤ℓ≤20 is the number of tines on the left, and  0r20 0≤r≤20 is the number of tines on the right.

Output

Output a single line describing the moose. For even pointed moose, output “Even  x x” where  x x is the points of the moose. For odd pointed moose, output “Odd  x x” where  x x is the points of the moose. If the moose has no tines, output “Not a moose

Sample Input 1 Sample Output 1
2 3
Odd 6
Sample Input 2 Sample Output 2
3 3
Even 6
Sample Input 3 Sample Output 3
0 0
Not a moose
签到题,不说了,最简单的一道。

#include
using namespace std;
int main()
{
    int l,r;
    while(~scanf("%d%d",&l,&r))
    {
        if(l==r&&(l||r))
        {
            cout<<"Even "<

K题:

Kayaking Trip

Nordic Collegiate Programming Contest 2017 题解_第6张图片
Solution to Sample Input 1, with kayaks replaced by canoes (cc by-sa NCPC 2017)
You are leading a kayaking trip with a mixed group of participants in the Stockholm archipelago, but as you are about to begin your final stretch back to the mainland you notice a storm on the horizon. You had better paddle as fast as you can to make sure you do not get trapped on one of the islands. Of course, you cannot leave anyone behind, so your speed will be determined by the slowest kayak. Time to start thinking; How should you distribute the participants among the kayaks to maximize your chance of reaching the mainland safely?

The kayaks are of different types and have different amounts of packing, so some are more easily paddled than others. This is captured by a speed factor  c c that you have already figured out for each kayak. The final speed  v v of a kayak, however, is also determined by the strengths  s1 s1 and  s2 s2 of the two people in the kayak, by the relation  v=c(s1+s2) v=c(s1+s2). In your group you have some beginners with a kayaking strength of  sb sb, a number of normal participants with strength  sn sn and some quite experienced strong kayakers with strength  se se.

Input

The first line of input contains three non-negative integers  b b n n, and  e e, denoting the number of beginners, normal participants, and experienced kayakers, respectively. The total number of participants,  b+n+e b+n+e, will be even, at least  2 2, and no more than  100000 100000. This is followed by a line with three integers  sb sb sn sn, and  se se, giving the strengths of the corresponding participants ( 1sb<sn<se1000 1≤sb). The third and final line contains  m=b+n+e2 m=b+n+e2 integers  c1,,cm c1,…,cm ( 1ci100000 1≤ci≤100000 for each  i i), each giving the speed factor of one kayak.

Output

Output a single integer, the maximum speed that the slowest kayak can get by distributing the participants two in each kayak.

Sample Input 1 Sample Output 1
3 1 0
40 60 90
18 20
1600
Sample Input 2 Sample Output 2
7 0 7
5 10 500
1 1 1 1 1 1 1
505
很明显,最小值最大,二分就行,judge时贪心的选择一对刚好能满足这个船的两个人就行。

#include 
using namespace std;
typedef long long LL;
const int maxn = 1000000 + 10;
int b, n, e;
int sb, sn, se;
int m;
int value[maxn];
double eps = 1e-7;
struct node{
    int numb, numn, nume;
    int sum;
    bool operator <(const node &res) const{
        return sum < res.sum;
    }
}Node[maxn];
bool judge(int x)
{
    int bb = b;
    int nn = n;
    int ee = e;
    for(int i = 1; i <= m; i++)
    {
        double down = (double)x / (double)value[i];
        int cnt = 0;
        if(bb >= 2)
        {
            Node[cnt].numb = 2;
            Node[cnt].numn = 0;
            Node[cnt].nume = 0;
            Node[cnt++].sum = sb + sb;
        }
        if(nn >= 2)
        {
            Node[cnt].numb = 0;
            Node[cnt].numn = 2;
            Node[cnt].nume = 0;
            Node[cnt++].sum = sn + sn;
        }
        if(ee >= 2)
        {
            Node[cnt].numb = 0;
            Node[cnt].numn = 0;
            Node[cnt].nume = 2;
            Node[cnt++].sum = se + se;
        }
        if(bb && nn)
        {
            Node[cnt].numb = 1;
            Node[cnt].numn = 1;
            Node[cnt].nume = 0;
            Node[cnt++].sum = sb + sn;
        }
        if(bb && ee)
        {
            Node[cnt].numb = 1;
            Node[cnt].numn = 0;
            Node[cnt].nume = 1;
            Node[cnt++].sum = sb + se;
        }
        if(nn && ee)
        {
            Node[cnt].numb = 0;
            Node[cnt].numn = 1;
            Node[cnt].nume = 1;
            Node[cnt++].sum = sn + se;
        }
        sort(Node, Node + cnt);
        int flag = false;
        for(int j = 0; j < cnt; j++)
        {
            if(down - (double)Node[j].sum <= eps)
            {
                flag = true;
                bb -= Node[j].numb;
                nn -= Node[j].numn;
                ee -= Node[j].nume;
                break;
            }
        }
        if(!flag) return false;
    }
    return true;
}
int main()
{
    scanf("%d%d%d", &b, &n, &e);
    m = (b + n + e) / 2;
    scanf("%d%d%d", &sb, &sn, &se);
    for(int i = 1; i <= m; i++)
    {
        scanf("%d", &value[i]);
    }
    int l = 0, r = 1000000000;
    int re = -1;
    while(l <= r)
    {
        int mid = (l + r)>>1;
        if(judge(mid))
        {
            re = mid;
            l = mid + 1;
        }
        else r = mid - 1;
    }
    printf("%d\n", re);
    return 0;
}


你可能感兴趣的:(Nordic Collegiate Programming Contest 2017 题解)