結果
| 問題 |
No.861 ケーキカット
|
| コンテスト | |
| ユーザー |
qwewe
|
| 提出日時 | 2025-05-14 13:03:25 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 9,052 bytes |
| コンパイル時間 | 2,775 ms |
| コンパイル使用メモリ | 97,044 KB |
| 実行使用メモリ | 19,144 KB |
| 最終ジャッジ日時 | 2025-05-14 13:05:06 |
| 合計ジャッジ時間 | 5,715 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | -- * 3 |
| other | TLE * 1 -- * 20 |
ソースコード
#include <iostream>
#include <vector>
#include <numeric>
#include <cmath>
#include <queue>
#include <limits>
#include <vector> // Ensure vector is included
#include <cstdlib> // For std::abs
// Detect GCC/Clang to use compiler builtins for optimization
// Builtins like __builtin_ctz and __builtin_popcount can speed up mask operations.
#if defined(__GNUC__) || defined(__clang__)
#define USE_BUILTINS
#endif
using namespace std;
// Use long long for deliciousness values and sums to avoid overflow, as values can be large.
typedef long long ll;
const int GRID_SIZE = 5; // The cake is 5x5
const int N = GRID_SIZE * GRID_SIZE; // Total number of cells (25)
// vals: 1D array storing deliciousness values. Cell (i, j) maps to index k = i * GRID_SIZE + j.
ll vals[N];
// adj: Adjacency list for the grid graph. adj[k] stores indices of neighbors of cell k.
vector<vector<int>> adj(N);
// total_sum: Stores the sum of deliciousness values of all cells in the cake.
ll total_sum = 0;
// Function to check connectivity of a subset of cells represented by a bitmask.
// Uses Breadth-First Search (BFS).
// Input:
// mask: An integer where the k-th bit is set if cell k is in the subset.
// current_sum_ptr: Pointer to a long long where the sum of deliciousness values of the connected component will be stored.
// Returns:
// true if the subset is connected, false otherwise.
// If true, *current_sum_ptr contains the sum of deliciousness values for the cells in the mask.
bool isConnectedOptimized(int mask, ll* current_sum_ptr) {
// An empty set (mask 0) is not a valid portion for A or B according to the problem statement.
if (mask == 0) return false;
// Find the index of the first cell included in the subset (mask).
// This cell will be the starting point for BFS.
// Using __builtin_ctz (count trailing zeros) is efficient if available.
#ifdef USE_BUILTINS
int start_node = __builtin_ctz(mask);
#else
// Fallback: linear scan to find the first set bit if builtins are not available.
int start_node = -1;
for(int i = 0; i < N; ++i) {
if ((mask >> i) & 1) { // Check if the i-th bit is set
start_node = i;
break;
}
}
// This check should ideally never fail if mask > 0.
if (start_node == -1) return false;
#endif
// BFS setup
int visited_mask = 0; // Bitmask to keep track of visited cells during BFS for this component.
queue<int> q; // Queue for BFS nodes to visit.
q.push(start_node); // Start BFS from the first node found.
visited_mask |= (1 << start_node); // Mark start_node as visited.
int count = 0; // Counter for the number of cells visited by BFS.
ll current_sum = 0; // Accumulator for the sum of deliciousness values in the connected component found by BFS.
// BFS traversal
while (!q.empty()) {
int u = q.front(); // Get the next cell index from the queue.
q.pop();
count++; // Increment the count of visited cells.
current_sum += vals[u]; // Add the deliciousness of the current cell to the sum.
// Explore neighbors of the current cell u using the precomputed adjacency list.
for (int v : adj[u]) {
// Check three conditions for neighbor v:
// 1. Is neighbor v part of the subset defined by the input mask? Check if v-th bit is set in 'mask'.
// 2. Has neighbor v not been visited yet in this BFS run? Check if v-th bit is not set in 'visited_mask'.
if (((mask >> v) & 1) && !((visited_mask >> v) & 1)) {
visited_mask |= (1 << v); // Mark neighbor v as visited.
q.push(v); // Add neighbor v to the queue for exploration.
}
}
}
// After BFS, check if the number of visited cells ('count') matches the
// total number of cells expected in the subset (population count of 'mask').
// Using __builtin_popcount is efficient if available.
int popcount;
#ifdef USE_BUILTINS
popcount = __builtin_popcount(mask);
#else
// Fallback: manual popcount implementation if builtins are not available.
popcount = 0;
int temp_mask = mask;
while (temp_mask > 0) {
// Clear the least significant set bit. Counting these operations gives popcount.
temp_mask &= (temp_mask - 1);
popcount++;
}
#endif
// If BFS visited exactly the number of cells present in the mask, the subset is connected.
if (count == popcount) {
*current_sum_ptr = current_sum; // Store the calculated sum of deliciousness.
return true; // Return true indicating the subset is connected.
} else {
// If the counts don't match, it means BFS didn't reach all cells in the mask,
// so the subset is not connected.
return false;
}
}
int main() {
// Optimize standard I/O operations for speed.
ios_base::sync_with_stdio(false);
cin.tie(NULL);
// Precompute the adjacency list for the grid graph.
// Each cell (i, j) is mapped to a linear index k = i * GRID_SIZE + j.
for (int i = 0; i < GRID_SIZE; ++i) {
for (int j = 0; j < GRID_SIZE; ++j) {
int k = i * GRID_SIZE + j;
// Add edge to cell above if not in the first row (i > 0).
if (i > 0) adj[k].push_back(k - GRID_SIZE);
// Add edge to cell below if not in the last row (i < GRID_SIZE - 1).
if (i < GRID_SIZE - 1) adj[k].push_back(k + GRID_SIZE);
// Add edge to cell left if not in the first column (j > 0).
if (j > 0) adj[k].push_back(k - 1);
// Add edge to cell right if not in the last column (j < GRID_SIZE - 1).
if (j < GRID_SIZE - 1) adj[k].push_back(k + 1);
}
}
// Read the deliciousness values (C_ij) for each cell from input.
// Store them in the 1D array `vals` using the linear index k.
// Calculate the total sum of deliciousness values for the entire cake.
for (int i = 0; i < GRID_SIZE; ++i) {
for (int j = 0; j < GRID_SIZE; ++j) {
ll val_ij;
cin >> val_ij; // Read C_ij value.
int k = i * GRID_SIZE + j; // Calculate the linear index k.
vals[k] = val_ij; // Store the value in the 1D array.
total_sum += val_ij; // Accumulate the total sum.
}
}
// Initialize the minimum difference found so far.
// Using -1 as a sentinel value to indicate that no valid partition has been found yet.
// Alternatively, use LLONG_MAX from <limits>.
ll min_diff = -1;
// Iterate through all possible non-empty proper subsets of cells represented by bitmasks.
// We only need to iterate through masks from 1 up to (but not including) 2^(N-1).
// This strategy ensures that each partition {S, V\S} is considered exactly once.
// For a mask 'm' representing subset S, its complement 'complement_m' represents V\S.
// If we check 'm', we don't need to check 'complement_m' later.
// Iterating up to 2^(N-1)-1 covers all subsets S where |S| <= N/2 (plus some with |S| > N/2 if N is even).
// Every partition pair {S, V\S} will have one member considered.
int limit = 1 << (N - 1); // The upper bound for the loop is 2^(N-1). Iteration runs for m = 1, ..., 2^(N-1)-1.
int full_mask = (1 << N) - 1; // A mask with all N bits set, representing the full set of cells.
for (int m = 1; m < limit; ++m) {
ll current_sum_A; // Variable to store the sum for subset A (represented by mask m).
// Check if subset A is connected. If yes, get its sum in current_sum_A.
if (isConnectedOptimized(m, ¤t_sum_A)) {
// If A is connected, calculate the mask for its complement subset B.
int complement_m = full_mask ^ m;
ll dummy_sum_B; // Temporary variable to pass to isConnected for B's connectivity check. Its value is not needed here.
// Check if the complement subset B is also connected.
if (isConnectedOptimized(complement_m, &dummy_sum_B)) {
// If both A and B are connected, this forms a valid partition of the cake.
// Calculate the sum for subset B using the total sum and A's sum: S_B = S_total - S_A.
ll current_sum_B = total_sum - current_sum_A;
// Calculate the absolute difference between the sums of A and B. Use std::abs for long long.
ll diff = std::abs(current_sum_A - current_sum_B);
// Update the minimum difference found so far if the current partition yields a smaller difference.
// Handle the initial case where min_diff is the sentinel value -1.
if (min_diff == -1 || diff < min_diff) {
min_diff = diff;
}
}
}
}
// Output the overall minimum difference found across all valid partitions.
cout << min_diff << endl;
return 0;
}
qwewe