Submission #69571774


Source Code Expand

#include <bits/stdc++.h>
using namespace std;

int N, t_i, t_j;
vector<vector<char>> grid;
set<pair<int, int>> revealed;
set<pair<int, int>> placed_treants;
int entrance_i, entrance_j;
int turn_count = 0;

int di[4] = {-1, 1, 0, 0};
int dj[4] = {0, 0, -1, 1};

// 预计算距离矩阵
vector<vector<int>> dist_from_entrance;
vector<vector<int>> dist_from_flower;

// 快速BFS计算距离
void bfs_distance(int si, int sj, vector<vector<int>>& dist, const vector<vector<char>>& map) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            dist[i][j] = INT_MAX;
        }
    }
    
    queue<pair<int, int>> q;
    q.push(make_pair(si, sj));
    dist[si][sj] = 0;
    
    while (!q.empty()) {
        int i = q.front().first;
        int j = q.front().second;
        q.pop();
        
        for (int d = 0; d < 4; d++) {
            int ni = i + di[d], nj = j + dj[d];
            if (ni >= 0 && ni < N && nj >= 0 && nj < N && 
                dist[ni][nj] == INT_MAX && map[ni][nj] == '.') {
                dist[ni][nj] = dist[i][j] + 1;
                q.push(make_pair(ni, nj));
            }
        }
    }
}

// 快速连通性检查 - 只检查是否可达,不计算路径
bool is_connected_fast(int si, int sj, int ei, int ej, const vector<vector<char>>& map) {
    if (map[si][sj] == 'T' || map[ei][ej] == 'T') return false;
    
    vector<vector<bool>> visited(N, vector<bool>(N, false));
    queue<pair<int, int>> q;
    q.push(make_pair(si, sj));
    visited[si][sj] = true;
    
    while (!q.empty()) {
        int i = q.front().first;
        int j = q.front().second;
        q.pop();
        
        if (i == ei && j == ej) return true;
        
        for (int d = 0; d < 4; d++) {
            int ni = i + di[d], nj = j + dj[d];
            if (ni >= 0 && ni < N && nj >= 0 && nj < N && 
                !visited[ni][nj] && map[ni][nj] == '.') {
                visited[ni][nj] = true;
                q.push(make_pair(ni, nj));
            }
        }
    }
    return false;
}

// 获取最短路径(简化版,只找一条路径)
vector<pair<int, int>> get_shortest_path_fast(int si, int sj, int ei, int ej, const vector<vector<char>>& map) {
    if (map[si][sj] == 'T' || map[ei][ej] == 'T') return {};
    
    vector<vector<pair<int, int>>> prev(N, vector<pair<int, int>>(N, make_pair(-1, -1)));
    vector<vector<bool>> visited(N, vector<bool>(N, false));
    queue<pair<int, int>> q;
    q.push(make_pair(si, sj));
    visited[si][sj] = true;
    
    while (!q.empty()) {
        int i = q.front().first;
        int j = q.front().second;
        q.pop();
        
        if (i == ei && j == ej) {
            vector<pair<int, int>> path;
            int cur_i = i, cur_j = j;
            while (cur_i != si || cur_j != sj) {
                path.push_back(make_pair(cur_i, cur_j));
                pair<int, int> p = prev[cur_i][cur_j];
                cur_i = p.first;
                cur_j = p.second;
            }
            path.push_back(make_pair(si, sj));
            reverse(path.begin(), path.end());
            return path;
        }
        
        // 优先选择更接近目标的方向
        vector<int> dir_priority = {0, 1, 2, 3};
        if (ei > i) swap(dir_priority[0], dir_priority[1]); // 优先向下
        if (ej > j) swap(dir_priority[2], dir_priority[3]); // 优先向右
        
        for (int d_idx = 0; d_idx < 4; d_idx++) {
            int d = dir_priority[d_idx];
            int ni = i + di[d], nj = j + dj[d];
            if (ni >= 0 && ni < N && nj >= 0 && nj < N && 
                !visited[ni][nj] && map[ni][nj] == '.') {
                visited[ni][nj] = true;
                prev[ni][nj] = make_pair(i, j);
                q.push(make_pair(ni, nj));
            }
        }
    }
    return {};
}

// 快速评估位置价值
int evaluate_position_fast(int i, int j, int p_i, int p_j, bool flower_revealed) {
    int score = 0;
    
    // 1. 距离花朵的远近
    int flower_dist = abs(i - t_i) + abs(j - t_j);
    score += max(0, 15 - flower_dist);
    
    // 2. 如果花朵已揭示,优先阻塞路径
    if (flower_revealed) {
        // 简单评估:如果这个位置在冒险者和花朵之间
        if ((i >= min(p_i, t_i) && i <= max(p_i, t_i)) && 
            (j >= min(p_j, t_j) && j <= max(p_j, t_j))) {
            score += 20;
        }
    } else {
        // 3. 如果花朵未揭示,在花朵周围形成保护
        if (flower_dist <= 3) {
            score += 25;
        }
        
        // 4. 在冒险者和花朵之间的位置
        int mid_i = (p_i + t_i) / 2;
        int mid_j = (p_j + t_j) / 2;
        if (abs(i - mid_i) + abs(j - mid_j) <= 2) {
            score += 15;
        }
    }
    
    // 5. 创建死胡同的潜力
    int revealed_neighbors = 0;
    for (int d = 0; d < 4; d++) {
        int ni = i + di[d], nj = j + dj[d];
        if (ni >= 0 && ni < N && nj >= 0 && nj < N) {
            if (revealed.find(make_pair(ni, nj)) != revealed.end()) {
                revealed_neighbors++;
            }
        }
    }
    
    // 如果周围有已揭示的单元格,这个位置更有价值
    score += revealed_neighbors * 3;
    
    return score;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    
    // 读取输入
    cin >> N >> t_i >> t_j;
    grid.resize(N, vector<char>(N));
    for (int i = 0; i < N; i++) {
        string s;
        cin >> s;
        for (int j = 0; j < N; j++) {
            grid[i][j] = s[j];
        }
    }
    
    entrance_i = 0;
    entrance_j = N / 2;
    revealed.insert(make_pair(entrance_i, entrance_j));
    
    // 初始化距离矩阵
    dist_from_entrance.resize(N, vector<int>(N, INT_MAX));
    dist_from_flower.resize(N, vector<int>(N, INT_MAX));
    
    // 预计算距离
    bfs_distance(entrance_i, entrance_j, dist_from_entrance, grid);
    bfs_distance(t_i, t_j, dist_from_flower, grid);
    
    // 主循环
    while (true) {
        turn_count++;
        int p_i, p_j;
        cin >> p_i >> p_j;
        
        int n;
        cin >> n;
        vector<pair<int, int>> new_revealed;
        for (int i = 0; i < n; i++) {
            int x, y;
            cin >> x >> y;
            revealed.insert(make_pair(x, y));
            new_revealed.push_back(make_pair(x, y));
        }
        
        // 检查是否到达花朵
        if (p_i == t_i && p_j == t_j) {
            break;
        }
        
        // 构建真实地图
        vector<vector<char>> real_map = grid;
        for (auto& pos : placed_treants) {
            real_map[pos.first][pos.second] = 'T';
        }
        
        // 构建试探地图
        vector<vector<char>> tentative_map(N, vector<char>(N, '.'));
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (revealed.find(make_pair(i, j)) != revealed.end()) {
                    tentative_map[i][j] = real_map[i][j];
                }
            }
        }
        
        // 获取可放置位置(限制数量)
        vector<pair<int, int>> available_positions;
        int max_positions = 100; // 限制评估的位置数量
        
        // 优先考虑关键区域的位置
        bool flower_revealed = revealed.find(make_pair(t_i, t_j)) != revealed.end();
        
        // 区域1: 花朵周围
        for (int i = max(0, t_i-3); i <= min(N-1, t_i+3) && available_positions.size() < max_positions; i++) {
            for (int j = max(0, t_j-3); j <= min(N-1, t_j+3); j++) {
                if (revealed.find(make_pair(i, j)) == revealed.end() && 
                    real_map[i][j] == '.') {
                    available_positions.push_back(make_pair(i, j));
                    if (available_positions.size() >= max_positions) break;
                }
            }
        }
        
        // 区域2: 冒险者和花朵之间
        if (available_positions.size() < max_positions) {
            int mid_i = (p_i + t_i) / 2;
            int mid_j = (p_j + t_j) / 2;
            for (int i = max(0, mid_i-2); i <= min(N-1, mid_i+2) && available_positions.size() < max_positions; i++) {
                for (int j = max(0, mid_j-2); j <= min(N-1, mid_j+2); j++) {
                    if (revealed.find(make_pair(i, j)) == revealed.end() && 
                        real_map[i][j] == '.' &&
                        find(available_positions.begin(), available_positions.end(), make_pair(i, j)) == available_positions.end()) {
                        available_positions.push_back(make_pair(i, j));
                        if (available_positions.size() >= max_positions) break;
                    }
                }
            }
        }
        
        // 区域3: 随机补充
        if (available_positions.size() < max_positions / 2) {
            // 如果关键区域位置太少,随机补充一些
            for (int i = 0; i < N && available_positions.size() < max_positions; i++) {
                for (int j = 0; j < N && available_positions.size() < max_positions; j++) {
                    if (revealed.find(make_pair(i, j)) == revealed.end() && 
                        real_map[i][j] == '.' &&
                        find(available_positions.begin(), available_positions.end(), make_pair(i, j)) == available_positions.end()) {
                        available_positions.push_back(make_pair(i, j));
                    }
                }
            }
        }
        
        if (available_positions.empty()) {
            cout << 0 << endl;
            continue;
        }
        
        // 快速选择最佳位置
        pair<int, int> best_pos = make_pair(-1, -1);
        int best_score = -1;
        
        // 限制评估的数量
        int max_evaluate = min(30, (int)available_positions.size());
        
        // 第一阶段:快速筛选
        vector<pair<int, pair<int, int>>> candidates;
        for (int idx = 0; idx < max_evaluate; idx++) {
            int i = available_positions[idx].first;
            int j = available_positions[idx].second;
            
            // 快速连通性检查
            vector<vector<char>> test_map = real_map;
            test_map[i][j] = 'T';
            if (!is_connected_fast(entrance_i, entrance_j, t_i, t_j, test_map)) {
                continue;
            }
            
            int score = evaluate_position_fast(i, j, p_i, p_j, flower_revealed);
            
            // 如果是花朵已揭示阶段,检查是否在路径上
            if (flower_revealed) {
                auto path = get_shortest_path_fast(p_i, p_j, t_i, t_j, tentative_map);
                for (const auto& pos : path) {
                    if (pos.first == i && pos.second == j) {
                        score += 30;
                        break;
                    }
                }
            }
            
            candidates.push_back(make_pair(score, make_pair(i, j)));
        }
        
        // 第二阶段:精细评估(只对前几名候选)
        if (!candidates.empty()) {
            sort(candidates.begin(), candidates.end(), greater<pair<int, pair<int, int>>>());
            
            // 只评估前3名候选的路径影响
            int top_n = min(3, (int)candidates.size());
            for (int i = 0; i < top_n; i++) {
                int score = candidates[i].first;
                int pos_i = candidates[i].second.first;
                int pos_j = candidates[i].second.second;
                
                // 计算路径长度影响
                if (flower_revealed) {
                    int original_length = get_shortest_path_fast(p_i, p_j, t_i, t_j, tentative_map).size();
                    if (original_length > 0) {
                        vector<vector<char>> test_tentative = tentative_map;
                        test_tentative[pos_i][pos_j] = 'T';
                        int new_length = get_shortest_path_fast(p_i, p_j, t_i, t_j, test_tentative).size();
                        if (new_length > 0) {
                            score += (new_length - original_length) * 2;
                        }
                    }
                }
                
                if (score > best_score) {
                    best_score = score;
                    best_pos = candidates[i].second;
                }
            }
        }
        
        // 输出结果
        if (best_pos.first != -1) {
            placed_treants.insert(best_pos);
            cout << 1 << " " << best_pos.first << " " << best_pos.second << endl;
        } else {
            // 尝试找到一个安全位置
            bool found = false;
            for (const auto& pos : available_positions) {
                vector<vector<char>> test_map = real_map;
                test_map[pos.first][pos.second] = 'T';
                if (is_connected_fast(entrance_i, entrance_j, t_i, t_j, test_map)) {
                    placed_treants.insert(pos);
                    cout << 1 << " " << pos.first << " " << pos.second << endl;
                    found = true;
                    break;
                }
            }
            if (!found) {
                cout << 0 << endl;
            }
        }
        
        // 防止超时
        if (turn_count > 2000) {
            cout << -1 << endl;
            break;
        }
    }
    
    return 0;
}

Submission Info

Submission Time
Task A - Treant's Forest
User a_computers_xh
Language C++ 23 (gcc 12.2)
Score 18786
Code Size 13777 Byte
Status AC
Exec Time 288 ms
Memory 3704 KiB

Compile Error

Main.cpp: In function ‘int main()’:
Main.cpp:240:88: warning: comparison of integer expressions of different signedness: ‘std::vector<std::pair<int, int> >::size_type’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare]
  240 |         for (int i = max(0, t_i-3); i <= min(N-1, t_i+3) && available_positions.size() < max_positions; i++) {
      |                                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
Main.cpp:245:52: warning: comparison of integer expressions of different signedness: ‘std::vector<std::pair<int, int> >::size_type’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare]
  245 |                     if (available_positions.size() >= max_positions) break;
      |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
Main.cpp:251:40: warning: comparison of integer expressions of different signedness: ‘std::vector<std::pair<int, int> >::size_type’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare]
  251 |         if (available_positions.size() < max_positions) {
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
Main.cpp:254:96: warning: comparison of integer expressions of different signedness: ‘std::vector<std::pair<int, int> >::size_type’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare]
  254 |             for (int i = max(0, mid_i-2); i <= min(N-1, mid_i+2) && available_positions.size() < max_positions; i++) {
      |                                                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
Main.cpp:260:56: warning: comparison of integer expressions of different signedness: ‘std::vector<std::pair<int, int> >::size_type’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare]
  260 |                         if (available_positions.size() >= max_positions) break;
      |                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
Main.cpp:267:40: warning: comparison of integer expressions of different signedness: ‘std::vector<std::pair<int, int> >::size_type’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare]
  267 |         if (available_positions.size() < max_positions / 2) {
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
Main.cpp:269:65: warning: comparison of integer expressions of different signedness: ‘std::vector<std::pair<int, int> >::size_type’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare]
  269 |             for (int i = 0; i < N && available_positions.size() < max_positions; i++) {
      |                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
Main.cpp:270:69: warning: comparison of integer expressions of different signedness: ‘std::vector<std::pair<int, int> >::size_type’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare]
  270 |                 for (int j = 0; j < N && available_positions.size() < max_positions; j++) {
      |                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~

Judge Result

Set Name test_ALL
Score / Max Score 18786 / 100000000000
Status
AC × 100
Set Name Test Cases
test_ALL test_0000.txt, test_0001.txt, test_0002.txt, test_0003.txt, test_0004.txt, test_0005.txt, test_0006.txt, test_0007.txt, test_0008.txt, test_0009.txt, test_0010.txt, test_0011.txt, test_0012.txt, test_0013.txt, test_0014.txt, test_0015.txt, test_0016.txt, test_0017.txt, test_0018.txt, test_0019.txt, test_0020.txt, test_0021.txt, test_0022.txt, test_0023.txt, test_0024.txt, test_0025.txt, test_0026.txt, test_0027.txt, test_0028.txt, test_0029.txt, test_0030.txt, test_0031.txt, test_0032.txt, test_0033.txt, test_0034.txt, test_0035.txt, test_0036.txt, test_0037.txt, test_0038.txt, test_0039.txt, test_0040.txt, test_0041.txt, test_0042.txt, test_0043.txt, test_0044.txt, test_0045.txt, test_0046.txt, test_0047.txt, test_0048.txt, test_0049.txt, test_0050.txt, test_0051.txt, test_0052.txt, test_0053.txt, test_0054.txt, test_0055.txt, test_0056.txt, test_0057.txt, test_0058.txt, test_0059.txt, test_0060.txt, test_0061.txt, test_0062.txt, test_0063.txt, test_0064.txt, test_0065.txt, test_0066.txt, test_0067.txt, test_0068.txt, test_0069.txt, test_0070.txt, test_0071.txt, test_0072.txt, test_0073.txt, test_0074.txt, test_0075.txt, test_0076.txt, test_0077.txt, test_0078.txt, test_0079.txt, test_0080.txt, test_0081.txt, test_0082.txt, test_0083.txt, test_0084.txt, test_0085.txt, test_0086.txt, test_0087.txt, test_0088.txt, test_0089.txt, test_0090.txt, test_0091.txt, test_0092.txt, test_0093.txt, test_0094.txt, test_0095.txt, test_0096.txt, test_0097.txt, test_0098.txt, test_0099.txt
Case Name Status Exec Time Memory
test_0000.txt AC 38 ms 3548 KiB
test_0001.txt AC 35 ms 3496 KiB
test_0002.txt AC 12 ms 3356 KiB
test_0003.txt AC 26 ms 3584 KiB
test_0004.txt AC 11 ms 3584 KiB
test_0005.txt AC 88 ms 3540 KiB
test_0006.txt AC 15 ms 3684 KiB
test_0007.txt AC 20 ms 3532 KiB
test_0008.txt AC 138 ms 3576 KiB
test_0009.txt AC 12 ms 3452 KiB
test_0010.txt AC 87 ms 3516 KiB
test_0011.txt AC 61 ms 3684 KiB
test_0012.txt AC 75 ms 3608 KiB
test_0013.txt AC 83 ms 3496 KiB
test_0014.txt AC 42 ms 3604 KiB
test_0015.txt AC 44 ms 3588 KiB
test_0016.txt AC 40 ms 3560 KiB
test_0017.txt AC 184 ms 3704 KiB
test_0018.txt AC 58 ms 3496 KiB
test_0019.txt AC 10 ms 3400 KiB
test_0020.txt AC 56 ms 3584 KiB
test_0021.txt AC 22 ms 3500 KiB
test_0022.txt AC 140 ms 3544 KiB
test_0023.txt AC 35 ms 3464 KiB
test_0024.txt AC 16 ms 3472 KiB
test_0025.txt AC 19 ms 3436 KiB
test_0026.txt AC 135 ms 3568 KiB
test_0027.txt AC 68 ms 3644 KiB
test_0028.txt AC 153 ms 3560 KiB
test_0029.txt AC 27 ms 3384 KiB
test_0030.txt AC 47 ms 3624 KiB
test_0031.txt AC 67 ms 3572 KiB
test_0032.txt AC 47 ms 3612 KiB
test_0033.txt AC 39 ms 3516 KiB
test_0034.txt AC 15 ms 3528 KiB
test_0035.txt AC 201 ms 3540 KiB
test_0036.txt AC 38 ms 3536 KiB
test_0037.txt AC 15 ms 3584 KiB
test_0038.txt AC 93 ms 3544 KiB
test_0039.txt AC 126 ms 3564 KiB
test_0040.txt AC 49 ms 3452 KiB
test_0041.txt AC 16 ms 3668 KiB
test_0042.txt AC 12 ms 3476 KiB
test_0043.txt AC 19 ms 3512 KiB
test_0044.txt AC 53 ms 3488 KiB
test_0045.txt AC 126 ms 3640 KiB
test_0046.txt AC 209 ms 3548 KiB
test_0047.txt AC 68 ms 3572 KiB
test_0048.txt AC 164 ms 3660 KiB
test_0049.txt AC 84 ms 3540 KiB
test_0050.txt AC 6 ms 3436 KiB
test_0051.txt AC 13 ms 3480 KiB
test_0052.txt AC 23 ms 3552 KiB
test_0053.txt AC 24 ms 3456 KiB
test_0054.txt AC 27 ms 3612 KiB
test_0055.txt AC 18 ms 3388 KiB
test_0056.txt AC 16 ms 3484 KiB
test_0057.txt AC 86 ms 3524 KiB
test_0058.txt AC 32 ms 3456 KiB
test_0059.txt AC 57 ms 3428 KiB
test_0060.txt AC 241 ms 3576 KiB
test_0061.txt AC 90 ms 3620 KiB
test_0062.txt AC 57 ms 3480 KiB
test_0063.txt AC 12 ms 3504 KiB
test_0064.txt AC 73 ms 3512 KiB
test_0065.txt AC 66 ms 3648 KiB
test_0066.txt AC 270 ms 3560 KiB
test_0067.txt AC 28 ms 3524 KiB
test_0068.txt AC 114 ms 3480 KiB
test_0069.txt AC 17 ms 3508 KiB
test_0070.txt AC 51 ms 3504 KiB
test_0071.txt AC 67 ms 3564 KiB
test_0072.txt AC 20 ms 3548 KiB
test_0073.txt AC 288 ms 3576 KiB
test_0074.txt AC 78 ms 3484 KiB
test_0075.txt AC 38 ms 3488 KiB
test_0076.txt AC 10 ms 3584 KiB
test_0077.txt AC 9 ms 3456 KiB
test_0078.txt AC 88 ms 3620 KiB
test_0079.txt AC 54 ms 3416 KiB
test_0080.txt AC 8 ms 3664 KiB
test_0081.txt AC 80 ms 3528 KiB
test_0082.txt AC 83 ms 3604 KiB
test_0083.txt AC 38 ms 3556 KiB
test_0084.txt AC 37 ms 3488 KiB
test_0085.txt AC 21 ms 3484 KiB
test_0086.txt AC 68 ms 3456 KiB
test_0087.txt AC 17 ms 3528 KiB
test_0088.txt AC 26 ms 3480 KiB
test_0089.txt AC 10 ms 3468 KiB
test_0090.txt AC 17 ms 3588 KiB
test_0091.txt AC 23 ms 3600 KiB
test_0092.txt AC 49 ms 3496 KiB
test_0093.txt AC 47 ms 3616 KiB
test_0094.txt AC 34 ms 3408 KiB
test_0095.txt AC 189 ms 3556 KiB
test_0096.txt AC 11 ms 3472 KiB
test_0097.txt AC 102 ms 3612 KiB
test_0098.txt AC 41 ms 3552 KiB
test_0099.txt AC 15 ms 3536 KiB