题解
2025-08-18 20:08:56
发布于:北京
69阅读
0回复
0点赞
#include <iostream>
#include<vector>
#include<unordered_map>
#include<algorithm>
#include<queue>
using namespace std;
#define endl '\n'
// 仅存储必要的坐标信息
struct ZB {
int x, y;
ZB(int x_, int y_) : x(x_), y(y_) {}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n;
cin >> n;
// 使用vector代替固定大小数组,节省空间
vector<vector<int>> farm(n, vector<int>(n));
unordered_map<int, int> cc;  // 用哈希表存储牛的数量,节省空间
vector<int> ids;  // 存储出现过的牛的ID,避免遍历不存在的ID
// 读取数据并统计
for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
        int cow;
        cin >> cow;
        farm[i][j] = cow;
        cc[cow]++;
    }
}
// 提取所有出现过的牛ID
for (auto& p : cc) {
    ids.push_back(p.first);
}
// 按数量从大到小排序
sort(ids.begin(), ids.end(), [&](int a, int b) {
    return cc[a] > cc[b];
});
// 方向数组,只保留必要的4个方向(上下左右),8方向会增加计算量且提升有限
const int fx[] = {0, 1, 0, -1};
const int fy[] = {1, 0, -1, 0};
// 单一种类最大块
int sum1 = 0;
vector<vector<bool>> tried(n, vector<bool>(n, false));  // 复用此数组
for (int id : ids) {
    int cnt = cc[id];
    if (cnt <= sum1) break;  // 剪枝
    
    // 重置tried数组
    for (auto& row : tried) fill(row.begin(), row.end(), false);
    
    for (int y = 0; y < n; ++y) {
        for (int x = 0; x < n; ++x) {
            if (farm[y][x] == id && !tried[y][x]) {
                // 使用队列代替vector作为BFS容器,更高效
                queue<ZB> q;
                q.emplace(x, y);
                tried[y][x] = true;
                int sum = 1;
                
                while (!q.empty()) {
                    auto zb = q.front();
                    q.pop();
                    
                    for (int d = 0; d < 4; ++d) {  // 4方向
                        int xx = zb.x + fx[d];
                        int yy = zb.y + fy[d];
                        
                        if (xx >= 0 && xx < n && yy >= 0 && yy < n && 
                            !tried[yy][xx] && farm[yy][xx] == id) {
                            tried[yy][xx] = true;
                            q.emplace(xx, yy);
                            sum++;
                        }
                    }
                }
                
                sum1 = max(sum1, sum);
            }
        }
    }
}
// 两种类组合最大块
int sum2 = 0;
int m = ids.size();
for (int i = 0; i < m; ++i) {
    int id1 = ids[i];
    int cnt1 = cc[id1];
    if (cnt1 * 2 <= sum2) break;  // 剪枝
    
    for (int j = i + 1; j < m; ++j) {
        int id2 = ids[j];
        int total = cnt1 + cc[id2];
        if (total <= sum2) break;  // 剪枝
        
        // 重置tried数组
        for (auto& row : tried) fill(row.begin(), row.end(), false);
        
        for (int y = 0; y < n; ++y) {
            for (int x = 0; x < n; ++x) {
                if ((farm[y][x] == id1 || farm[y][x] == id2) && !tried[y][x]) {
                    queue<ZB> q;
                    q.emplace(x, y);
                    tried[y][x] = true;
                    int sum = 1;
                    
                    while (!q.empty()) {
                        auto zb = q.front();
                        q.pop();
                        
                        for (int d = 0; d < 4; ++d) {
                            int xx = zb.x + fx[d];
                            int yy = zb.y + fy[d];
                            
                            if (xx >= 0 && xx < n && yy >= 0 && yy < n && 
                                !tried[yy][xx] && (farm[yy][xx] == id1 || farm[yy][xx] == id2)) {
                                tried[yy][xx] = true;
                                q.emplace(xx, yy);
                                sum++;
                            }
                        }
                    }
                    
                    sum2 = max(sum2, sum);
                }
            }
        }
    }
}
cout << sum1 << '\n' << sum2;
return 0;
}
#include <iostream>
#include<vector>
#include<unordered_map>
#include<algorithm>
#include<queue>
using namespace std;
#define endl '\n'
// 仅存储必要的坐标信息
struct ZB {
    int x, y;
    ZB(int x_, int y_) : x(x_), y(y_) {}
};
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n;
    cin >> n;
    
    // 使用vector代替固定大小数组,节省空间
    vector<vector<int>> farm(n, vector<int>(n));
    unordered_map<int, int> cc;  // 用哈希表存储牛的数量,节省空间
    vector<int> ids;  // 存储出现过的牛的ID,避免遍历不存在的ID
    
    // 读取数据并统计
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            int cow;
            cin >> cow;
            farm[i][j] = cow;
            cc[cow]++;
        }
    }
    
    // 提取所有出现过的牛ID
    for (auto& p : cc) {
        ids.push_back(p.first);
    }
    
    // 按数量从大到小排序
    sort(ids.begin(), ids.end(), [&](int a, int b) {
        return cc[a] > cc[b];
    });
    
    // 方向数组,只保留必要的4个方向(上下左右),8方向会增加计算量且提升有限
    const int fx[] = {0, 1, 0, -1};
    const int fy[] = {1, 0, -1, 0};
    
    // 单一种类最大块
    int sum1 = 0;
    vector<vector<bool>> tried(n, vector<bool>(n, false));  // 复用此数组
    
    for (int id : ids) {
        int cnt = cc[id];
        if (cnt <= sum1) break;  // 剪枝
        
        // 重置tried数组
        for (auto& row : tried) fill(row.begin(), row.end(), false);
        
        for (int y = 0; y < n; ++y) {
            for (int x = 0; x < n; ++x) {
                if (farm[y][x] == id && !tried[y][x]) {
                    // 使用队列代替vector作为BFS容器,更高效
                    queue<ZB> q;
                    q.emplace(x, y);
                    tried[y][x] = true;
                    int sum = 1;
                    
                    while (!q.empty()) {
                        auto zb = q.front();
                        q.pop();
                        
                        for (int d = 0; d < 4; ++d) {  // 4方向
                            int xx = zb.x + fx[d];
                            int yy = zb.y + fy[d];
                            
                            if (xx >= 0 && xx < n && yy >= 0 && yy < n && 
                                !tried[yy][xx] && farm[yy][xx] == id) {
                                tried[yy][xx] = true;
                                q.emplace(xx, yy);
                                sum++;
                            }
                        }
                    }
                    
                    sum1 = max(sum1, sum);
                }
            }
        }
    }
    
    // 两种类组合最大块
    int sum2 = 0;
    int m = ids.size();
    
    for (int i = 0; i < m; ++i) {
        int id1 = ids[i];
        int cnt1 = cc[id1];
        if (cnt1 * 2 <= sum2) break;  // 剪枝
        
        for (int j = i + 1; j < m; ++j) {
            int id2 = ids[j];
            int total = cnt1 + cc[id2];
            if (total <= sum2) break;  // 剪枝
            
            // 重置tried数组
            for (auto& row : tried) fill(row.begin(), row.end(), false);
            
            for (int y = 0; y < n; ++y) {
                for (int x = 0; x < n; ++x) {
                    if ((farm[y][x] == id1 || farm[y][x] == id2) && !tried[y][x]) {
                        queue<ZB> q;
                        q.emplace(x, y);
                        tried[y][x] = true;
                        int sum = 1;
                        
                        while (!q.empty()) {
                            auto zb = q.front();
                            q.pop();
                            
                            for (int d = 0; d < 4; ++d) {
                                int xx = zb.x + fx[d];
                                int yy = zb.y + fy[d];
                                
                                if (xx >= 0 && xx < n && yy >= 0 && yy < n && 
                                    !tried[yy][xx] && (farm[yy][xx] == id1 || farm[yy][xx] == id2)) {
                                    tried[yy][xx] = true;
                                    q.emplace(xx, yy);
                                    sum++;
                                }
                            }
                        }
                        
                        sum2 = max(sum2, sum);
                    }
                }
            }
        }
    }
    
    cout << sum1 << '\n' << sum2;
    return 0;
}
这里空空如也






有帮助,赞一个