洛谷P2392 揹包問題

題目鏈接: 傳送門

在這裏插入圖片描述
在這裏插入圖片描述

看完題目就感覺是個貪心,樣例也能推過去,於是交了以下代碼:

/*
 * @Author: hesorchen
 * @Date: 2020-04-14 10:33:26
 * @LastEditTime: 2020-05-13 14:29:51
 * @Link: https://hesorchen.github.io/
 */

#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define endl '\n'
#define PI cos(-1)
#define PB push_back
#define ll long long
#define INF 0x3f3f3f3f
#define mod 1000000009
#define lowbit(abcd) (abcd & (-abcd))
#define fre                              \
    {                                    \
        freopen("in.txt", "r", stdin);   \
        freopen("out.txt", "w", stdout); \
    }

ll a1[50];
ll a2[50];
ll a3[50];
ll a4[50];
int main()
{
    ll s1, s2, s3, s4;
    cin >> s1 >> s2 >> s3 >> s4;
    for (int i = 1; i <= s1; i++)
        cin >> a1[i];
    for (int i = 1; i <= s2; i++)
        cin >> a2[i];
    for (int i = 1; i <= s3; i++)
        cin >> a3[i];
    for (int i = 1; i <= s4; i++)
        cin >> a4[i];
    ll ans = 0;
    sort(a1 + 1, a1 + 1 + s1, greater<int>());
    sort(a2 + 1, a2 + 1 + s2, greater<int>());
    sort(a3 + 1, a3 + 1 + s3, greater<int>());
    sort(a4 + 1, a4 + 1 + s4, greater<int>());
    ll pos;
    ll l, r;
    l = 1, r = 2;
    while (l <= s1)
    {
        if (a1[l] > 0 && a1[r] > 0)
            a1[l]--, a1[r]--;
        else if (a1[l] > 0)
            a1[l]--;
        ans++;
        if (a1[r] == 0 && a1[l] == 0)
            l += 2, r += 2;
        else if (a1[r] == 0)
            r += 1;
        else if (a1[l] == 0)
            l += 1, r += 1;
    }

    l = 1, r = 2;
    while (l <= s2)
    {
        if (a2[l] > 0 && a2[r] > 0)
            a2[l]--, a2[r]--;
        else if (a2[l] > 0)
            a2[l]--;
        ans++;
        if (a2[r] == 0 && a2[l] == 0)
            l += 2, r += 2;
        else if (a2[r] == 0)
            r += 1;
        else if (a2[l] == 0)
            l += 1, r += 1;
    }

    l = 1, r = 2;
    while (l <= s3)
    {
        if (a3[l] > 0 && a3[r] > 0)
            a3[l]--, a3[r]--;
        else if (a3[l] > 0)
            a3[l]--;
        ans++;
        if (a3[r] == 0 && a3[l] == 0)
            l += 2, r += 2;
        else if (a3[r] == 0)
            r += 1;
        else if (a3[l] == 0)
            l += 1, r += 1;
    }

    l = 1, r = 2;
    while (l <= s4)
    {
        if (a4[l] > 0 && a4[r] > 0)
            a4[l]--, a4[r]--;
        else if (a4[l] > 0)
            a4[l]--;
        ans++;
        if (a4[r] == 0 && a4[l] == 0)
            l += 2, r += 2;
        else if (a4[r] == 0)
            r += 1;
        else if (a4[l] == 0)
            l += 1, r += 1;
    }
    cout << ans << endl;

    return 0;
}

結果一個測試點都沒過。看了一下題解,發現很多人都以爲是貪心,果然沒有經過系統證明的猜想都是耍流氓

解題思路:我們可以將每一門課的複習點分成兩組,並且保證兩組的差值儘可能小,那麼就可以轉換成01揹包問題,揹包的最大容量爲sum2\frac{sum}{2},求出揹包最多能裝多少物品。結果就是sumsum2sum-\frac{sum}{2}

AC代碼:

/*
 * @Author: hesorchen
 * @Date: 2020-04-14 10:33:26
 * @LastEditTime: 2020-05-13 14:57:12
 * @Link: https://hesorchen.github.io/
 */

#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define endl '\n'
#define PI cos(-1)
#define PB push_back
#define ll long long
#define INF 0x3f3f3f3f
#define mod 1000000009
#define lowbit(abcd) (abcd & (-abcd))
#define fre                              \
    {                                    \
        freopen("in.txt", "r", stdin);   \
        freopen("out.txt", "w", stdout); \
    }

ll a1[50];
ll a2[50];
ll a3[50];
ll a4[50];

ll dp[500000];
int main()
{
    ll s1, s2, s3, s4;
    cin >> s1 >> s2 >> s3 >> s4;
    for (int i = 1; i <= s1; i++)
        cin >> a1[i];
    for (int i = 1; i <= s2; i++)
        cin >> a2[i];
    for (int i = 1; i <= s3; i++)
        cin >> a3[i];
    for (int i = 1; i <= s4; i++)
        cin >> a4[i];
    ll ans = 0;
    ll sum, sum_2;

    fill(dp, dp + 600, 0);
    sum = 0;
    for (int i = 1; i <= s1; i++)
        sum += a1[i];
    sum_2 = sum;
    sum = sum / 2;
    for (int i = 1; i <= s1; i++)
        for (int j = sum; j >= 0; j--)
            if (j >= a1[i])
                dp[j] = max(dp[j], dp[j - a1[i]] + a1[i]);
    ans += sum_2 - dp[sum];

    fill(dp, dp + 600, 0);
    sum = 0;
    for (int i = 1; i <= s2; i++)
        sum += a2[i];
    sum_2 = sum;
    sum = sum / 2;
    for (int i = 1; i <= s2; i++)
        for (int j = sum; j >= 0; j--)
            if (j >= a2[i])
                dp[j] = max(dp[j], dp[j - a2[i]] + a2[i]);
    ans += sum_2 - dp[sum];

    fill(dp, dp + 600, 0);
    sum = 0;
    for (int i = 1; i <= s3; i++)
        sum += a3[i];
    sum_2 = sum;
    sum = sum / 2;
    for (int i = 1; i <= s3; i++)
        for (int j = sum; j >= 0; j--)
            if (j >= a3[i])
                dp[j] = max(dp[j], dp[j - a3[i]] + a3[i]);
    ans += sum_2 - dp[sum];

    fill(dp, dp + 600, 0);
    sum = 0;
    for (int i = 1; i <= s4; i++)
        sum += a4[i];
    sum_2 = sum;
    sum = sum / 2;
    for (int i = 1; i <= s4; i++)
        for (int j = sum; j >= 0; j--)
            if (j >= a4[i])
                dp[j] = max(dp[j], dp[j - a4[i]] + a4[i]);
    ans += sum_2 - dp[sum];

    cout << ans << endl;

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