結果
問題 |
No.506 限られたジャパリまん
|
ユーザー |
![]() |
提出日時 | 2025-05-14 13:13:20 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 7,057 bytes |
コンパイル時間 | 853 ms |
コンパイル使用メモリ | 88,972 KB |
実行使用メモリ | 7,844 KB |
最終ジャッジ日時 | 2025-05-14 13:14:18 |
合計ジャッジ時間 | 7,317 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 12 WA * 13 |
ソースコード
#include <iostream> #include <vector> #include <string> #include <numeric> // Not strictly needed, but good practice for potentially using standard algorithms #include <algorithm> // For std::max, though manual comparison is used here #include <vector> // Use __builtin_popcount if available (typically on GCC/Clang) #if defined(__GNUC__) || defined(__clang__) #define USE_BUILTIN_POPCOUNT #endif using namespace std; // Define long long for convenience, especially for path counts that can exceed 32-bit int limits typedef long long ll; ll H, W; // Grid dimensions (East-West H meters, North-South W meters) int K; // Number of friends int P; // Number of Japari buns available // Structure to store friend information struct FriendInfo { int x, y; // Coordinates of the friend string name; // Name of the friend }; vector<FriendInfo> friends; // Vector to store information about all K friends ll MOD = 1000000007; // Modulo value for path counting // Function to count set bits (population count) in an integer // This determines how many friends are chosen in a subset represented by a bitmask int countSetBits(int n) { #ifdef USE_BUILTIN_POPCOUNT // Use the compiler's built-in function for efficiency if available return __builtin_popcount(n); #else // Fallback manual implementation using Brian Kernighan's algorithm // Works for non-negative integers int count = 0; unsigned int val = static_cast<unsigned int>(n); // Use unsigned int for safety with bitwise ops while (val > 0) { val &= (val - 1); // Clears the least significant set bit count++; } return count; #endif } // Dynamic Programming function to calculate the number of shortest paths // from (0,0) to (H,W) for a given subset of friends allowed to pass (represented by mask). // Friends whose corresponding bit in 'mask' is 1 are passable. Others are obstacles. ll calculate_paths(int mask) { // Create a grid to mark obstacle locations. True if obstacle, false otherwise. vector<vector<bool>> is_obstacle(H + 1, vector<bool>(W + 1, false)); for (int i = 0; i < K; ++i) { // If the i-th bit in the mask is 0, this friend is NOT given a bun and acts as an obstacle. if (!((mask >> i) & 1)) { // Mark the friend's location as an obstacle // The problem guarantees friend coordinates are within grid bounds [0,H] x [0,W] is_obstacle[friends[i].x][friends[i].y] = true; } } // DP table: dp[x][y] will store the number of shortest paths from (0,0) to (x,y) vector<vector<ll>> dp(H + 1, vector<ll>(W + 1, 0)); // Base case: The starting point (0,0). // The problem states (0,0) is never an obstacle location. if (is_obstacle[0][0]) return 0; // Safety check: if start is blocked, 0 paths. dp[0][0] = 1; // There is one way to be at the start: just be there. // Fill the DP table iteratively for (int x = 0; x <= H; ++x) { for (int y = 0; y <= W; ++y) { // If the current cell (x,y) is an obstacle, no paths can go through it. if (is_obstacle[x][y]) { dp[x][y] = 0; // Ensure dp value is 0 for obstacles continue; // Skip calculation for this cell, paths cannot terminate or pass through here. } // For non-obstacle cells, calculate paths reaching it. // Paths can only come from the West (x-1, y) or South (x, y-1). // Add paths coming from West (moving East to reach (x,y)) if (x > 0) { // We add dp[x-1][y] because any path to (x-1,y) can be extended East to (x,y). // No need to check if (x-1, y) is obstacle, as if it were, dp[x-1][y] would be 0. dp[x][y] = (dp[x][y] + dp[x-1][y]) % MOD; } // Add paths coming from South (moving North to reach (x,y)) if (y > 0) { // Similarly, add dp[x][y-1] dp[x][y] = (dp[x][y] + dp[x][y-1]) % MOD; } // Note: The base case dp[0][0]=1 is correctly handled. dp[1][0] will get value from dp[0][0], // dp[0][1] will get value from dp[0][0]. dp[1][1] will get value from dp[0][1] and dp[1][0]. } } // The final answer for this mask is the number of paths to the destination (H, W). return dp[H][W]; } int main() { // Use faster I/O operations ios_base::sync_with_stdio(false); cin.tie(NULL); // Read input values: grid dimensions H, W, number of friends K, number of buns P cin >> H >> W >> K >> P; // Read friend data: coordinates (x,y) and name for each friend friends.resize(K); for (int i = 0; i < K; ++i) { cin >> friends[i].x >> friends[i].y >> friends[i].name; } ll max_paths = -1; // Initialize max_paths to -1 to track the maximum paths found so far. // -1 helps distinguish between 0 paths and initial state. int best_mask = -1; // Initialize best_mask to -1, stores the mask yielding max_paths. // Iterate through all possible subsets of friends using bitmasks from 0 to 2^K - 1 for (int mask = 0; mask < (1 << K); ++mask) { // A subset is valid if the number of friends chosen (number of set bits) is at most P. if (countSetBits(mask) <= P) { // Calculate the number of shortest paths for the current subset choice. ll current_paths = calculate_paths(mask); // If the number of paths for this subset is greater than the current maximum found: if (current_paths > max_paths) { max_paths = current_paths; // Update the maximum path count. best_mask = mask; // Update the mask that achieved this maximum. } } } // --- Output Results --- // If max_paths is still -1 (should technically not happen for H, W >= 1 as (0,0) is reachable) // or if max_paths is 0, it means the destination (H,W) is unreachable for all valid subsets. // In this case, output 0 as required. if (max_paths <= 0) { cout << 0 << endl; } else { // Otherwise, output the maximum number of paths found. cout << max_paths << endl; // Then, output the names of the friends corresponding to the set bits in the best_mask. // Iterate through friends based on their original input order (index i). for (int i = 0; i < K; ++i) { // Check if the i-th bit is set in the best_mask. if ((best_mask >> i) & 1) { // If set, this friend was given a bun in the optimal solution. Print their name. cout << friends[i].name << endl; } } } // The problem statement asks for a final newline. Standard output with `endl` handles newlines after each print. // No extra blank line is typically needed unless explicitly specified. return 0; // Indicate successful execution }