제출 #1251631

#제출 시각아이디문제언어결과실행 시간메모리
1251631noob1234은행 (IZhO14_bank)C++20
100 / 100
205 ms78408 KiB
#include <iostream>
#include <fstream>

#include <algorithm>
#include <numeric>
#include <vector>

using namespace std;

int main()
{

    int numSalaries, numNotes;
    vector<int> salaries, notes;

    cin >> numSalaries >> numNotes;

    for (int i = 0; i < numSalaries; i++)
    {
        int temp; cin >> temp;
        salaries.push_back(temp);
    }

    for (int i = 0; i < numNotes; i++)
    {
        int temp; cin >> temp;
        notes.push_back(temp);
    }

    int total_salaries = accumulate(salaries.begin(), salaries.end(), 0);
    int total_banknotes = accumulate(notes.begin(), notes.end(), 0);

    if (total_salaries > total_banknotes)
    {
        cout << "NO" << endl;
        return 0;
    }

    sort(salaries.rbegin(), salaries.rend());

    vector<int> prefix(numSalaries + 1, 0);
    for (int i = 1; i <= numSalaries; i++)
    {
        prefix[i] = prefix[i - 1] + salaries[i - 1];
    }


    vector<int> sums_mask(1 << numNotes, 0);
    for (int mask = 0; mask < (1 << numNotes); mask++) // creates a mask for every possible way to take some amount of notes, this is to find all possible combinations and their sum
    {
        for (int i = 0; i < numNotes; i++)
        {
            if (mask & (1 << i))
            {
                sums_mask[mask] += notes[i];
            }
        }
    }

    vector<vector<bool>> dp(1 << numNotes, vector<bool>(numSalaries + 1, false));
    dp[0][0] = true;
    bool found_solution = false;

    for (int mask = 0; mask < (1 << numNotes); mask++) // iterate over all combinations of banknotes
    {
        if (found_solution) break;

        for (int index = 0; index <= numSalaries; index++) // iterate over all salaries
        {
            if (found_solution) break;
            if (!dp[mask][index]) continue; // if if the first "index" salaries cannot be paid, skip 

            if (index == numSalaries) // prev condition didn't trigger so first "index" salaries can be paid with mask
            {                        // since index is the number of salaries, all salaries can be paid
                found_solution = true;
                break;
            }

            int current_sum = sums_mask[mask] - prefix[index];

            // re-iterate over all banknotes, except this time, skip used banknotes already used in the current mask
            for (int j = 0; j < numNotes; j++)
            {
                if (found_solution) break;
                if (mask & (1 << j)) continue; // skip if current banknote is used in the current mask
                int new_mask = mask | (1 << j); // add the chosen banknote to the mask
                int new_sum = current_sum + notes[j];

                if (new_sum < salaries[index]) // if the new sum is smaller than the current salary, update the state for the given index
                {
                    if (!dp[new_mask][index])
                    {
                        dp[new_mask][index] = true;
                    }
                }
                else if (new_sum == salaries[index]) // if the new sum matches the current salary, move to the next salary
                {
                    if (index + 1 == numSalaries) // if next index is the end of the salaries array, solution found
                    {
                        found_solution = true; break;
                    }
                    else
                    {
                        // update the state for the next salary index
                        if (!dp[new_mask][index + 1])
                        {
                            dp[new_mask][index + 1] = true;
                        }
                    }
                }
            }
        }
    }

    if (found_solution)
    {
        cout << "YES" << endl;
    }
    else
    {
        // If not found during the loop, check the table for any solution
        for (int mask = 0; mask < (1 << numNotes); mask++)
        {
            if (dp[mask][numSalaries])
            {
                found_solution = true;
                break;
            }
        }
        cout << (found_solution ? "YES" : "NO") << endl;
    }

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...