列表

详情


NC17497. Class Division

描述

There are n students in a school. The final exams are over and the results are out. Student i scored si points in the final exam.

You are the principal of the school and you want to divide the students into m classes. The i-th class should contain at least li students and at most ri students. Each student must belong to exactly one class.

The score of a class is defined as the average scores of all the students in the class. The score of the school is the sum of the scores of all classes. Your task is to find the maximum possible score of the school.

输入描述

The first line contains a single integer n (1 ≤ n ≤ 250), denoting the number of students.

The next line contains n space-separated integers, s1, s2, ..., sn (1 ≤ si ≤ 106).

The next line contains a single integer m (1 ≤ m ≤ 30), denoting the number of classes.

The next m lines contains two space-separated integers each, li, ri, describing the i-th class.

It is guaranteed that the input is chosen such that there exist a way to assign all the students into classes.

输出描述

Print the only number — the answer for the problem. Your answer is considered correct if its absolute or relative error does not exceed 10-6.

Formally, let your answer be a, and the jury's answer be b. Your answer is considered correct if .

示例1

输入:

5
3 6 1 2 5
3
1 3
1 1
2 3

输出:

13.0000000000

说明:

The optimal strategy is to assign the students with scores 1, 2, 3 into the third class, assign the student with score 5 into the first class and assign the student with score 6 into the second class. Then, the scores of the classes are 5, 6, \frac{1 + 2 + 3}{3} = 2 respectively. The score of the school is 5 + 6 + 2 = 13.

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 821ms, 内存消耗: 608K, 提交时间: 2018-08-10 10:35:08

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
 
const int N = 255;
int a[N];
double dp[35][N];
pair<int, int> pi[N];
#define x first
#define y second
 
bool cmp(pair<int, int> a, pair<int, int> b) {
    if (a.y != b.y) return a.y < b.y;
    return a.x < b.x;
}
 
 
void update(double &x, double y) {
    x = max(x, y);
}
 
double get_random(int n, int m) {
    int c[35], sum[35], b[35];
    for (int i = 1; i <= m; i++) c[i] = i;
    random_shuffle(c + 1, c + m + 1);
    double ans = 0, pre = 0;
    for (int t = 1; t <= 2000000; t++) {
        int p = rand() % m + 1, q = rand() % m + 1;
        if (p == q) continue;
        if (p > q) swap(p, q);
        if (t % 20)
          swap(c[p], c[q]);
        else reverse(c + p + 1, c + q + 1);
        sum[m + 1] = 0;
        b[m + 1] = 0;
        for (int j = m; j >= 1; j--) {
            sum[j] = sum[j + 1] + pi[c[j]].y;
            b[j] = b[j + 1] + pi[c[j]].x;
        }
 
        double tmp = 0;
        int pos = 0;
        for (int i = 1; i <= m; i++) {
            int mi = b[i + 1], mx = sum[i + 1];
            /*
            mi <= n - pos - p <= mx
            */
            int lt = max(pi[c[i]].x, -mx - pos + n);
            int rt = min(pi[c[i]].y, -mi - pos + n);
            while (lt > rt) cout << mi << " " << mx << " " << pi[c[i]].x << " " << pi[c[i]].y << " " << pos << " " << lt << " " << rt << endl;
            tmp += 1.0 * (a[pos + lt] - a[pos]) / lt;
            pos += lt;
        }
        ans = max(ans, tmp);
        if (tmp > pre) {
            pre = tmp;
        } else {
            if (t % 20) swap(c[p], c[q]);
            else reverse(c + p + 1, c + q + 1);
        }
 
 
    }
    return ans;
}
 
int main()
{
    int n, m;
    while (scanf("%d", &n) != EOF) {
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        sort(a + 1, a + n + 1);
        reverse(a + 1, a + n + 1);
        for (int i = 2; i <= n; i++) a[i] += a[i- 1];
        scanf("%d", &m);
        for (int i = 1; i <= m; i++) scanf("%d%d", &pi[i].x, &pi[i].second);
        sort(pi + 1, pi + m + 1, cmp);
        for (int i = 0; i <= m; i++)
            for (int j = 0; j <= n; j++)
                dp[i][j] = -1e20;
 
        dp[0][0] = 0;
        for (int i = 0; i < m; i++)
            for (int j = 0; j <= n; j++) {
                if (dp[i][j] < -1e8) continue;
                for (int k = pi[i + 1].x; k <= pi[i + 1].y; k++) {
                    if (j + k > n) continue;
                    update(dp[i + 1][j + k], dp[i][j] + 1.0 * (a[j + k] - a[j]) / k);
                }
            }
 
        double ans = get_random(n, m);
        printf("%.20lf\n", max(ans, dp[m][n]));
    }
    return 0;
}

C++ 解法, 执行用时: 464ms, 内存消耗: 500K, 提交时间: 2022-05-31 09:05:41

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
 
const int N=255;
int a[N];
double dp[35][N];
pair<int,int>pi[N];
 
bool cmp(pair<int,int>a, pair<int,int>b){
    if (a.y!=b.y) return a.y<b.y;
    return a.x<b.x;
}
 
inline void update(double &x,double y){if(y>x) x=y;}
 
double get_random(int n, int m){
    int c[35],sum[35],b[35];
    for (int i=1;i<=m;i++) c[i]=i;
    random_shuffle(c+1,c+m+1);
    double ans=0,pre=0;
    for(int t=1;t<=2000000;t++){
        int p=rand()%m+1,q=rand()%m+1;
        if(p==q) continue;
        if (p>q) swap(p,q);
        if(t%20) swap(c[p],c[q]);
        else reverse(c+p+1,c+q+1);
        sum[m+1]=0;
        b[m+1]=0;
        for(int j=m;j>=1;j--){
            sum[j]=sum[j+1]+pi[c[j]].y;
            b[j]=b[j+1]+pi[c[j]].x;
        }
        double tmp=0;
        int pos=0;
        for(int i=1;i<=m;i++){
            int mi=b[i+1],mx=sum[i+1];
			int lt=max(pi[c[i]].x,-mx-pos+n);
            int rt=min(pi[c[i]].y,-mi-pos+n);
            while (lt > rt) cout<<mi<<" "<<mx<<" "<<pi[c[i]].x<<" "<<pi[c[i]].y<<" "<<pos<<" "<<lt<<" "<<rt<<"\n";
            tmp+=1.0*(a[pos+lt]-a[pos])/lt;
            pos+=lt;
        }
        ans=max(ans,tmp);
        if(tmp>pre){
            pre=tmp;
        }else{
            if(t%20) swap(c[p],c[q]);
            else reverse(c+p+1,c+q+1);
        }
    }
    return ans;
}
 
signed main(){
    int n, m;
    while (scanf("%d", &n) != EOF) {
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        reverse(a+1,a+n+1);
        for(int i=2;i<=n;i++) a[i]+=a[i- 1];
        scanf("%d", &m);
        for(int i=1;i<=m;i++) scanf("%d%d",&pi[i].x,&pi[i].y);
        sort(pi+1,pi+m+1,cmp);
        for (int i=0;i<=m;i++)
            for (int j=0;j<=n;j++)
                dp[i][j]=-1e20;

        dp[0][0]=0;
        for(int i=0;i<m;i++)
            for(int j=0;j<=n;j++){
                if(dp[i][j]<-1e8) continue;
                for (int k=pi[i + 1].x;k<=pi[i + 1].y;k++){
                    if(j+k>n) continue;
                    update(dp[i+1][j+k],dp[i][j]+1.0*(a[j+k]-a[j])/k);
                }
            }
 
        double ans=get_random(n,m);
        printf("%.20lf\n", max(ans,dp[m][n]));
    }
    return 0;
}

上一题