Submission #1189242

#TimeUsernameProblemLanguageResultExecution timeMemory
1189242Zakir060Detecting Molecules (IOI16_molecules)C++20
Compilation error
0 ms0 KiB
#include <vector> // For std::vector #include <numeric> // Potentially useful, but not strictly needed here #include <algorithm> // For std::sort #include <utility> // For std::pair /* * This implementation is for the C++ interface where the function * directly returns a std::vector<int>. * A C interface adapter is provided further down. */ // Structure to store molecule weight along with its original index struct Molecule { long long weight; // Use long long for weight to handle potential large values and sums int index; // Original index (0 to n-1) }; // Custom comparison function for sorting Molecules in descending order of weight. // If weights are equal, sorting by index makes the result deterministic (though not required). bool compareMoleculesDesc(const Molecule& a, const Molecule& b) { if (a.weight != b.weight) { return a.weight > b.weight; // Primary sort: higher weight first } return a.index < b.index; // Secondary sort: lower index first (arbitrary but consistent) } /** * @brief Finds a subset of molecules whose total weight falls within the range [l, u]. * * @param l_int The lower bound of the detection range (inclusive). * @param u_int The upper bound of the detection range (inclusive). * @param w A constant reference to a vector containing the weights of the molecules. * @return A vector containing the original indices (0-based) of the molecules * in a valid subset. Returns an empty vector if no such subset exists. * * @details * The algorithm leverages the problem's constraint that u - l >= w_max - w_min. * It employs a greedy strategy: * 1. Filter out molecules heavier than the upper bound 'u'. * 2. Immediately return if any single molecule's weight falls within [l, u]. * 3. Sort the remaining potential candidate molecules (those with weight <= u) * in descending order of weight. * 4. Greedily add molecules from the sorted list (heaviest first) to a running sum, * as long as the sum does not exceed 'u'. * 5. After trying all candidates, check if the final sum is greater than or equal to 'l'. * If it is, the indices of the molecules added form a valid subset. * Otherwise (if the final sum is less than 'l'), no subset satisfying the * conditions exists according to this greedy strategy, and due to the problem's * constraint, this implies no solution exists at all. */ std::vector<int> find_subset(int l_int, int u_int, const std::vector<int>& w) { // Use long long for bounds and sums to prevent potential overflow, // as n * max(w) can exceed 32-bit limits. long long l = l_int; long long u = u_int; int n = w.size(); std::vector<Molecule> molecules_to_consider; molecules_to_consider.reserve(n); // Reserve space for efficiency // 1. Filter molecules and Check for Single-Molecule Solutions for (int i = 0; i < n; ++i) { long long current_weight = w[i]; // Use long long consistently // Check if this single molecule is already a valid subset if (current_weight >= l && current_weight <= u) { return {i}; // Found a solution with just one molecule } // Only consider molecules with weight <= u for potential combination. // Molecules with weight > u cannot be part of any valid sum <= u. // We also implicitly ignore molecules with weight >= l here because // they were handled by the single-molecule check above. if (current_weight < l) { // Only molecules lighter than l need combining molecules_to_consider.push_back({current_weight, i}); } // If current_weight > u, it's simply not added. } // 2. Sort the candidates (those with weight < l) in descending order std::sort(molecules_to_consider.begin(), molecules_to_consider.end(), compareMoleculesDesc); long long current_sum = 0; std::vector<int> current_subset_indices; // Optimization: Reserve capacity close to the number of candidates current_subset_indices.reserve(molecules_to_consider.size()); // 3. Greedy Selection (Descending Order) // Iterate through the sorted candidate molecules (heaviest first) for (const auto& mol : molecules_to_consider) { // Add the molecule to the subset if doing so does NOT exceed the upper bound 'u'. if (current_sum + mol.weight <= u) { current_sum += mol.weight; current_subset_indices.push_back(mol.index); // OPTIONAL check: If the sum reaches the target range [l, u] // we could potentially return immediately. However, the standard // greedy approach here finishes building the sum first. Let's stick // to the logic of building the largest possible sum <= u first. // if (current_sum >= l) { // return current_subset_indices; // Early exit if sum enters range // } } } // 4. Final Check // After iterating through all potential candidates, check if the accumulated sum // meets the lower bound 'l'. We already know current_sum <= u from the loop condition. if (current_sum >= l) { // The greedy approach successfully found a subset sum within [l, u] return current_subset_indices; } else { // The largest sum constructible greedily (descending) without exceeding 'u' // is still less than 'l'. The problem's constraint implies no other subset // will work either. return {}; // Return an empty vector indicating no solution found } } // --- C Interface Adapter --- // This part provides the wrapper function required for the C language interface. // It assumes the C++ function `find_subset` defined above is available. #ifdef __cplusplus extern "C" { #endif // We need C++ standard library headers if this were compiled separately. // Assuming they are available from the C++ code above. /** * @brief C interface function to find a subset sum in range [l, u]. * * @param l_int The lower bound of the detection range. * @param u_int The upper bound of the detection range. * @param w_arr Array of molecule weights. * @param n The number of molecules. * @param result Output array (pre-allocated, assumed size n) to store indices * of the found subset. * @return The number of elements in the found subset (size of the subset), * or 0 if no such subset exists. */ int find_subset_c_interface(int l_int, int u_int, int* w_arr, int n, int* result) { // Create a C++ std::vector from the input C array for convenience std::vector<int> w_vec(w_arr, w_arr + n); // Call the core C++ function implementation std::vector<int> subset_indices = find_subset(l_int, u_int, w_vec); // Process the result for the C interface if (!subset_indices.empty()) { int count = 0; // Copy the indices from the result vector to the C array 'result' for (int index : subset_indices) { // It's assumed 'result' is large enough to hold 'n' elements. result[count++] = index; } return count; // Return the number of indices found } else { // No subset was found return 0; } } #ifdef __cplusplus } // extern "C" #endif

Compilation message (stderr)

molecules.h:1:9: warning: #pragma once in main file
    1 | #pragma once
      |         ^~~~
molecules_c.h:1:9: warning: #pragma once in main file
    1 | #pragma once
      |         ^~~~
/usr/bin/ld: /tmp/cc7LoLPA.o: in function `main':
grader.cpp:(.text.startup+0x173): undefined reference to `find_subset(int, int, std::vector<int, std::allocator<int> >)'
collect2: error: ld returned 1 exit status