题解
2025-08-18 20:08:56
发布于:北京
47阅读
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;
}
这里空空如也
有帮助,赞一个