【linmo】北大百炼1414:Life Line:模拟+DFS

题目OpenJudge - 1414:Life Line

题解:模拟+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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值