結果
問題 |
No.584 赤、緑、青の色塗り
|
ユーザー |
![]() |
提出日時 | 2025-05-14 13:01:26 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 7,504 bytes |
コンパイル時間 | 793 ms |
コンパイル使用メモリ | 86,152 KB |
実行使用メモリ | 7,844 KB |
最終ジャッジ日時 | 2025-05-14 13:03:42 |
合計ジャッジ時間 | 5,580 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 6 |
other | AC * 7 TLE * 1 -- * 6 |
ソースコード
#include <iostream> #include <vector> #include <map> // Define a structure for the state key to be used in the map. // This improves readability and organization compared to using tuples or vectors directly. struct StateKey { int r, g, b; // Counts of Red, Green, Blue colors used so far int p1; // Color of the last cell (cell i) int p2; // Color of the second to last cell (cell i-1) // Colors are represented as integers: 0:Red, 1:Green, 2:Blue, 3:Empty // Define the less than operator '<'. This is required for std::map keys // to maintain order and allow efficient lookups. bool operator<(const StateKey& other) const { // Compare components in a fixed order. If any component differs, // the comparison result is determined. If all components match up to the last one, // compare the last component. if (r != other.r) return r < other.r; if (g != other.g) return g < other.g; if (b != other.b) return b < other.b; if (p1 != other.p1) return p1 < other.p1; return p2 < other.p2; } }; // Use std::map to store the DP states. The key is the StateKey struct, // and the value is the count of ways to reach that state (long long for potentially large counts). // We use two maps, `dp[0]` and `dp[1]`, to represent the DP states for the current step (i) // and the next step (i+1). This technique is often called "ping-pong" or double buffering. std::map<StateKey, long long> dp[2]; // Define the modulus for calculations, as required by the problem statement. long long MOD = 1000000007; int main() { // Use faster I/O operations by disabling synchronization with C stdio // and unlinking cin from cout. std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); int N, R, G, B; // Grid size N, target counts R, G, B std::cin >> N >> R >> G >> B; // Basic feasibility check: The total number of required colored cells // cannot exceed the total number of cells in the grid. // If R+G+B > N, it's impossible to satisfy the requirements. if (R + G + B > N) { std::cout << 0 << std::endl; return 0; } // Initialize the DP. The state before processing the first cell (at index 0) is: // 0 Red, 0 Green, 0 Blue cells used. // We assume the two fictitious cells before the grid start (-1 and 0) were Empty (color code 3). // There is 1 way to reach this initial state. dp[0][{0, 0, 0, 3, 3}] = 1; int current_dp_idx = 0; // Index (0 or 1) to access the current DP table // The main DP loop iterates N times, corresponding to processing cells 1 through N. for (int i = 0; i < N; ++i) { int next_dp_idx = 1 - current_dp_idx; // Index for the DP table for the next step dp[next_dp_idx].clear(); // Clear the map for the next state calculation to ensure it's fresh. // Optimization: If the current DP table is empty, it means no valid states were reached // in the previous step. Thus, no further states can be reached. We can break early. if (dp[current_dp_idx].empty()) { break; } // Iterate through all reachable states ending at cell i (stored in dp[current_dp_idx]) for (auto const& [current_state, count] : dp[current_dp_idx]) { // `current_state` contains {r, g, b, p1, p2} information after processing cell i. // `count` is the number of ways to reach this state. // Unpack state variables from the key for easier access int r = current_state.r; int g = current_state.g; int b = current_state.b; int p1 = current_state.p1; // Color of cell i int p2 = current_state.p2; // Color of cell i-1 // Try placing each possible color (R, G, B, E) at the next cell, i+1 for (int new_p1 = 0; new_p1 < 4; ++new_p1) { // Loop through colors 0:R, 1:G, 2:B, 3:E int next_r = r, next_g = g, next_b = b; // Initialize counts for the next state bool is_new_cell_colored = (new_p1 != 3); // Check if the new cell is colored or empty // Update color counts based on the color being placed at cell i+1 // Also check if the target count for that color has already been reached. if (new_p1 == 0) { // Placing Red if (r >= R) continue; // Cannot place Red if R count is already met/exceeded next_r++; } else if (new_p1 == 1) { // Placing Green if (g >= G) continue; // Cannot place Green if G count is already met/exceeded next_g++; } else if (new_p1 == 2) { // Placing Blue if (b >= B) continue; // Cannot place Blue if B count is already met/exceeded next_b++; } // No count change needed if placing an Empty cell (new_p1 == 3) // Check rule constraints before adding the state transition: // Constraint 1: No adjacent identical colors. // Compare the color of cell i+1 (new_p1) with the color of cell i (p1). // This check only applies if the new cell is colored. if (is_new_cell_colored && new_p1 == p1) { continue; // Invalid transition: results in RR, GG, or BB pattern } // Constraint 2: No three consecutive colored cells. // Check if placing `new_p1` at cell i+1 would create a sequence of three colored cells. // This happens if cell i+1, cell i, and cell i-1 are all colored. bool is_p1_colored = (p1 != 3); // Was cell i colored? bool is_p2_colored = (p2 != 3); // Was cell i-1 colored? if (is_new_cell_colored && is_p1_colored && is_p2_colored) { continue; // Invalid transition: results in a CCC pattern } // If all constraints are satisfied, this transition is valid. // Construct the StateKey for the resulting state after placing `new_p1` at cell i+1. // The new state has updated counts {next_r, next_g, next_b}. // The last color is `new_p1`. The second to last color is the previous last color `p1`. StateKey next_state = {next_r, next_g, next_b, new_p1, p1}; // Add the number of ways (`count`) from the current path to the total count // for the `next_state` in the `next_dp_idx` table. Perform addition modulo MOD. dp[next_dp_idx][next_state] = (dp[next_dp_idx][next_state] + count) % MOD; } } // After processing all states in the current DP table, switch context for the next iteration. current_dp_idx = next_dp_idx; } // After the loop finishes (N iterations), dp[current_dp_idx] contains states for the full grid of size N. long long total_ways = 0; // Sum up the counts for all final states that exactly match the target R, G, B counts. for (auto const& [final_state, count] : dp[current_dp_idx]) { if (final_state.r == R && final_state.g == G && final_state.b == B) { total_ways = (total_ways + count) % MOD; } } // Output the final answer. std::cout << total_ways << std::endl; return 0; }