题解:模拟+DFS
代码:
#include <iostream>
#include <vector>
#include <string.h>
using namespace std;
const int maxn = 15;
int tri_map[maxn][maxn]; // 存储三角图的二维数组
pair<int,int> record[maxn][maxn]; // 用于记录的二维数组,每一个单元为pair
// 若first元素为-1,则表示未遍历过
// 对于根节点(每一个同数字集群,都设立一个根节点),其存储的内容为<集群周围 0 节点的个数,集群内元素个数>
// 而对于其他结点,存储的值为根节点位置
// 例如:对于数字为4的集群,若根节点的位置为[0][3],集群有5个4,且与集群相邻的0结点有2个
// 则根节点存储的record为<2,4>,其他结点均为<0,3>
int n, c; // N值,C值
void dfs(int i, int j, pair<int, int> ori_p, int ori_v); // dfs函数声明
void deal_dfs(int ii, int jj, int ori_v, pair<int, int>ori_p){ // 处理函数
if (tri_map[ii][jj] == ori_v) { // 若为相同结点(也就是可连通,则继续dfs)
dfs(ii, jj, ori_p, ori_v);
}
else if (tri_map[ii][jj] == 0 && record[ii][jj] != ori_p) { // 若为0结点,且该0未记录过,则记录
record[ii][jj] = ori_p; // 更新该0结点的record为当前集群根节点位置,表示已经记录过
record[ori_p.first][ori_p.second].first++; // 值++
}
}
void dfs(int i, int j, pair<int, int> ori_p, int ori_v) { // 采用dfs遍历图
record[i][j] = ori_p; // 更新record
record[ori_p.first][ori_p.second].second++; // 更新根节点所记录的集群结点数
// 下述进行边界判断,若仍可探索,则用dfs探索
if (i > j) { // 方向为:上和右(两者判断条件一致)
int ii = i - 1;int jj = j;
for (int k = 0;k < 2;k++) {
ii += k;jj += k;
if (record[ii][jj].first == -1) { deal_dfs(ii, jj, ori_v, ori_p); }
}
}
// 方向为左
if (j > 0) { int ii = i;int jj = j - 1;if (record[ii][jj].first == -1) { deal_dfs(ii, jj, ori_v, ori_p); } }
// 方向为下
if (i < n - 1) { int ii = i + 1;int jj = j;if (record[ii][jj].first == -1) { deal_dfs(ii, jj, ori_v, ori_p); } }
// 方向为左上
if (i > 0 && j > 0) { int ii = i - 1;int jj = j - 1;if (record[ii][jj].first == -1) { deal_dfs(ii, jj, ori_v, ori_p); } }
// 方向为右下
if (i < n - 1 && j < n - 1) { int ii = i + 1;int jj = j + 1;if (record[ii][jj].first == -1) { deal_dfs(ii, jj, ori_v, ori_p); } }
return;
}
void score(int& res) { // 计算分数
// 在放入了石子后的图里做dfs,记录此次分数
for (int x = 0;x < n;x++) {
for (int y = 0;y <= x;y++) {
if (tri_map[x][y] == 0) { continue; }
if (record[x][y].first == -1) {
record[x][y] = pair<int, int>(0, 0); // 初始化根节点
dfs(x, y, pair<int, int>(x, y), tri_map[x][y]);
record[x][y].first -= x; // 此处为消除dfs在根节点的bug
record[x][y].second -= y; // 此处为消除dfs在根节点的bug
if (record[x][y].first == 0) { // 若满足移走条件,则计算得分
(tri_map[x][y] == c) ? res -= record[x][y].second : res += record[x][y].second;
}
}
}
}
}
int main() {
while (cin >> n >> c) {
if (n == 0 && c == 0) { break; }
memset(tri_map, -1, sizeof(tri_map)); // 初始化图
for (int i = 0;i < n;i++) { // 读入图
for (int j = 0;j <= i;j++) {
cin >> tri_map[i][j];
}
}
int max_s = -n * n - 5;
// 遍历图,找到0结点,模拟放入石子操作,并计算分数
for (int i = 0;i < n;i++) {
for (int j = 0;j <= i;j++) {
if (tri_map[i][j] == 0) {
tri_map[i][j] = c;
memset(record, -1, sizeof(record));
int res = 0;
score(res); // 计算分数
tri_map[i][j] = 0;
max_s = max(max_s, res); // 更新得分
continue;
}
}
}
cout << max_s << endl; // 输出得分
}
return 0;
}