結果
| 問題 |
No.640 76本のトロンボーン
|
| コンテスト | |
| ユーザー |
qwewe
|
| 提出日時 | 2025-05-14 13:09:30 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 10,077 bytes |
| コンパイル時間 | 1,349 ms |
| コンパイル使用メモリ | 97,248 KB |
| 実行使用メモリ | 11,300 KB |
| 最終ジャッジ日時 | 2025-05-14 13:10:48 |
| 合計ジャッジ時間 | 4,875 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | -- * 2 |
| other | AC * 7 TLE * 1 -- * 7 |
ソースコード
#include <iostream>
#include <vector>
#include <string>
#include <vector>
#include <numeric>
#include <algorithm>
#include <map>
using namespace std;
// Grid size
int N;
// Grid representation
vector<string> grid;
// Structure to represent a trombone placement
struct Trombone {
int id; // Unique identifier for the trombone placement
int type; // 0 for horizontal, 1 for vertical
int rc_idx; // row index for horizontal, column index for vertical (0-based)
int start_pos; // Indicates start position:
// For horizontal: 1 means covering columns 0 to N-2, 2 means columns 1 to N-1
// For vertical: 1 means covering rows 0 to N-2, 2 means rows 1 to N-1
};
// List of all valid trombone placements found
vector<Trombone> trombones;
// Adjacency list representation of the conflict graph
// Maps a trombone ID to a list of IDs of trombones it conflicts with
map<int, vector<int>> adj;
// Stores the maximum size of the independent set found so far
int max_is_size = 0;
// List of all trombone IDs (assumed to be 0 to total_trombones-1)
vector<int> nodes_list;
// Tracks which trombones are currently selected in the recursive search
vector<bool> current_selection;
/**
* @brief Recursive backtracking function to find the Maximum Independent Set (MIS).
*
* Finds the maximum number of trombones that can be placed without conflicts.
* It explores possibilities by trying to include or exclude each trombone placement.
*
* @param k_idx Index of the current trombone in nodes_list being considered.
* @param current_max The size of the independent set built so far in the current recursive path.
*/
void find_max_is_recursive(int k_idx, int current_max) {
int num_nodes = nodes_list.size();
// Base case: If all trombones have been considered
if (k_idx == num_nodes) {
// Update the global maximum MIS size found
max_is_size = max(max_is_size, current_max);
return;
}
// Get the ID of the current trombone being considered
int node_id = nodes_list[k_idx];
// Pruning optimization: If the current path plus all remaining nodes cannot possibly
// exceed the best MIS size found so far, then prune this branch.
if (current_max + (num_nodes - k_idx) <= max_is_size) {
return;
}
// Branch 1: Try including the current trombone (node_id) in the independent set
bool can_include = true;
// Check if node_id exists in the adjacency list map
if (adj.count(node_id)) {
// Check if including node_id conflicts with any previously selected trombone
// A conflict occurs if any neighbor of node_id is already selected.
// Since we process nodes in order (0 to num_nodes-1), we only need to check neighbors
// that have already been processed (their decision made).
// The `current_selection` array tracks this.
for (int neighbor_id : adj.at(node_id)) {
// Ensure neighbor_id is within bounds and check if it's selected
if (neighbor_id < current_selection.size() && current_selection[neighbor_id]) {
can_include = false;
break;
}
}
}
// If it's safe to include node_id
if (can_include) {
// Mark node_id as selected
current_selection[node_id] = true;
// Recurse for the next trombone, incrementing the current IS size
find_max_is_recursive(k_idx + 1, current_max + 1);
// Backtrack: Unmark node_id to explore other possibilities
current_selection[node_id] = false;
}
// Branch 2: Try excluding the current trombone (node_id) from the independent set
// Recurse for the next trombone without changing the current IS size
find_max_is_recursive(k_idx + 1, current_max);
}
int main() {
// Faster I/O
ios_base::sync_with_stdio(false);
cin.tie(NULL);
// Read grid size N
cin >> N;
// Read grid state
grid.resize(N);
for (int i = 0; i < N; ++i) {
cin >> grid[i];
}
// Assign unique IDs starting from 0
int current_id = 0;
// Identify all valid horizontal trombone placements
for (int r = 0; r < N; ++r) {
// Check placement type 1: Row r, columns 0 to N-2
bool possible1 = true;
if (N > 1) { // A trombone requires at least length 1 (N>=2)
for (int c = 0; c < N - 1; ++c) {
if (grid[r][c] == '#') { // Check for obstacles
possible1 = false;
break;
}
}
// If no obstacles found, add this placement as a valid trombone
if (possible1) {
trombones.push_back({current_id++, 0, r, 1});
}
}
// Check placement type 2: Row r, columns 1 to N-1
bool possible2 = true;
if (N > 1) {
for (int c = 1; c < N; ++c) {
if (grid[r][c] == '#') { // Check for obstacles
possible2 = false;
break;
}
}
// If no obstacles found, add this placement
if (possible2) {
trombones.push_back({current_id++, 0, r, 2});
}
}
}
// Identify all valid vertical trombone placements
for (int c = 0; c < N; ++c) {
// Check placement type 1: Column c, rows 0 to N-2
bool possible1 = true;
if (N > 1) {
for (int r = 0; r < N - 1; ++r) {
if (grid[r][c] == '#') { // Check for obstacles
possible1 = false;
break;
}
}
// If valid, add placement
if (possible1) {
trombones.push_back({current_id++, 1, c, 1});
}
}
// Check placement type 2: Column c, rows 1 to N-1
bool possible2 = true;
if (N > 1) {
for (int r = 1; r < N; ++r) {
if (grid[r][c] == '#') { // Check for obstacles
possible2 = false;
break;
}
}
// If valid, add placement
if (possible2) {
trombones.push_back({current_id++, 1, c, 2});
}
}
}
// Total number of valid trombone placements identified
int total_trombones = trombones.size();
// If no trombones can be placed, the answer is 0
if (total_trombones == 0) {
cout << 0 << endl;
return 0;
}
// Build the conflict graph represented by the adjacency list `adj`
for (int i = 0; i < total_trombones; ++i) {
for (int j = i + 1; j < total_trombones; ++j) {
Trombone t1 = trombones[i];
Trombone t2 = trombones[j];
bool conflict = false; // Flag to indicate if t1 and t2 conflict
// Case 1: Both are horizontal trombones
if (t1.type == 0 && t2.type == 0) {
// Conflict if they are in the same row
if (t1.rc_idx == t2.rc_idx) {
conflict = true;
}
// Case 2: Both are vertical trombones
} else if (t1.type == 1 && t2.type == 1) {
// Conflict if they are in the same column
if (t1.rc_idx == t2.rc_idx) {
conflict = true;
}
// Case 3: One horizontal, one vertical trombone
} else {
// Determine which is horizontal (h_trom) and which is vertical (v_trom)
Trombone h_trom = (t1.type == 0) ? t1 : t2;
Trombone v_trom = (t1.type == 1) ? t1 : t2;
// Get coordinates and start types
int r = h_trom.rc_idx; // row index (0-based) of horizontal trombone
int h_start_col = h_trom.start_pos; // start type (1 or 2) of horizontal trombone
int c = v_trom.rc_idx; // column index (0-based) of vertical trombone
int v_start_row = v_trom.start_pos; // start type (1 or 2) of vertical trombone
// Convert row/col indices to 1-based for easier logic matching with problem statement
int r_1based = r + 1;
int c_1based = c + 1;
// Check if the horizontal trombone covers cell (r, c)
bool h_covers = false;
if (h_start_col == 1 && c_1based >= 1 && c_1based <= N - 1) h_covers = true; // Type 1 covers cols 1 to N-1
if (h_start_col == 2 && c_1based >= 2 && c_1based <= N) h_covers = true; // Type 2 covers cols 2 to N
// Check if the vertical trombone covers cell (r, c)
bool v_covers = false;
if (v_start_row == 1 && r_1based >= 1 && r_1based <= N - 1) v_covers = true; // Type 1 covers rows 1 to N-1
if (v_start_row == 2 && r_1based >= 2 && r_1based <= N) v_covers = true; // Type 2 covers rows 2 to N
// Conflict occurs if both cover the intersection cell (r, c)
if (h_covers && v_covers) {
conflict = true;
}
}
// If a conflict exists, add edges between their IDs in the adjacency list
if (conflict) {
adj[t1.id].push_back(t2.id);
adj[t2.id].push_back(t1.id);
}
}
}
// Prepare for the recursive search
// Fill nodes_list with trombone IDs (0 to current_id-1)
for(int i=0; i<current_id; ++i) nodes_list.push_back(i);
// Resize the selection tracking vector to hold status for all IDs
current_selection.resize(current_id, false);
// Start the recursive backtracking search for the Maximum Independent Set
find_max_is_recursive(0, 0);
// Output the maximum size found
cout << max_is_size << endl;
return 0;
}
qwewe