【2019網易校招】籃球隊

題目描述
小Q是籃球訓練隊的教練,籃球隊新加入了N名隊員,第i名隊員的籃球水平值爲ai
小Q現在要把他們按照以下的要求分爲A隊和B隊進行訓練:
1、A隊的隊員水平值之和嚴格大於B隊的隊員水平值之和
2、對於A隊中的任意一名隊員,如果把他分配到B隊,A隊的水平值之和就會嚴格小於B隊的水平值之和。
3、每個隊員必須要加入一個隊伍
小Q現在想知道有多少種方案可以按照以上要求完成分隊。
題目鏈接

輸入描述:

輸入包括兩行, 輸入的第一行爲一個正整數n(2 <= N <= 50), 表示隊員的數量。
第二行包括N個正整數 ai(1 <= ai <= 6 × 104), 表示每名隊員的籃球水平值, 以空格分割。

輸出描述:

輸出一個正整數, 表示方案數。

示例1
輸入

4
5 4 7 6

輸出

2

AC代碼:

常數優化版本

#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 0x3f3f3f3f;

int dp[600000 * 50 + 1] = {0};

int gcd(int a, int b)
{
    /*if (a > b) 
        swap(a, b);*/
    return b ? gcd(b, a % b) : a;
}

ll solve(int *arr, int n)
{
    sort(arr, arr + n, greater<int>());
    int GCD_Number = arr[0];
    for (int i = 1; i < n; i++)
        GCD_Number = gcd(GCD_Number, arr[i]);
    ll tot = 0;
    //cout << "GCD_Number = " << GCD_Number << endl;
    for (int i = 0; i < n; i++)
    {
        arr[i] /= GCD_Number;	//常數優化,tot指數減小
        tot += arr[i];
    }
    ll ans = 0;
    
    dp[0] = 1;
    //for (int i = 1; i < maxn; i++)
    //    dp[i] = 0;
    for (int i = 0; i < n; i++)
    {
        for (ll j = tot; j >= arr[i]; j--)
        {
            dp[j] += dp[j - arr[i]];
            if (j > tot - j && j - arr[i] < tot - j + arr[i])
                ans += dp[j - arr[i]];
        }
    }
    return ans;
}

int main()
{
    ios::sync_with_stdio(false);
    int n;
    while (cin >> n)
    {
        int* arr = new int[n];
        //ll tot = 0;
        int tmp = 1;
        for (int i = 0; i < n; i++)
        {
            cin >> arr[i];
            //tot += arr[i];
        }
        ll ans = 0;
        ans = solve(arr, n);
        cout << ans << endl;
    }
    return 0;
}

無常數優化版本

#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
 
using namespace std;
 
typedef long long ll;
const int maxn = 0x3f3f3f3f;
 
int dp[600000 * 50 + 1] = {0};
 
/*int gcd(int a, int b)
{
    if (a > b)
        swap(a, b);
    return b ? gcd(b, b % a) : a;
}*/
 
ll solve(int *arr, int n, ll tot)
{
    sort(arr, arr + n, greater<int>());
    /*int GCD_Number = arr[0];
    for (int i = 1; i < n; i++)
        GCD_Number = gcd(GCD_Number, arr[i]);
    for (int i = 0; i < n; i++)
    {
        arr[i] /= GCD_Number;
        tot -= arr[i];
    }*/
    ll ans = 0;
     
    dp[0] = 1;
    //for (int i = 1; i < maxn; i++)
    //    dp[i] = 0;
    for (int i = 0; i < n; i++)
    {
        for (ll j = tot; j >= arr[i]; j--)
        {
            dp[j] += dp[j - arr[i]];
            if (j > tot - j && j - arr[i] < tot - j + arr[i])
                ans += dp[j - arr[i]];
        }
    }
    return ans;
}
 
int main()
{
    ios::sync_with_stdio(false);
    int n;
    while (cin >> n)
    {
        int* arr = new int[n];
        ll tot = 0;
        int tmp = 1;
        for (int i = 0; i < n; i++)
        {
            cin >> arr[i];
            tot += arr[i];
        }
        ll ans = 0;
        ans = solve(arr, n, tot);
        cout << ans << endl;
    }
    return 0;
}

時空消耗對比:


圖1 無常數優化代碼時空消耗



圖2 常數優化代碼時空消耗

常數優化後,
時間減少

104 ms

佔比減少

301197301\frac{301 - 197}{301} × 100% \approx 34.6 %

空間減少

5260 KB

佔比減少

12312687212312\frac{12312- 6872}{12312} × 100% \approx 44.2%

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章