2023编码大赛(2)

博客围绕一个双方轮流放置5种门,以点亮自己灯、灭掉他人灯的游戏展开。解题思路是建立打分系统,并采用极大极小算法,还给出了代码初稿,涉及C++开发语言和算法运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

双方轮流放置5种门,尽可能点亮自己的灯,灭掉他人的灯。

思路:

建立打分系统,采用极大极小算法。

代码初稿:

struct Node {
	int id;
	char type;// P G L  power gate light  
	int in1, in2; //无效id设为-1
	int out1, out2; //无效id设为-1
	char gateType; //type=G时,gateType有意义,分别为  DAONMZ  Z表示未知
	bool isMine;  //type=G L时,isMine有意义
	int value[4]{ -1, - 1, - 1, - 1 }; //in1 in2 out1 out2的信号,-1未知0黄1红, 只需要把电源模块的out1初始化即可
};

int gatePower(char c) {
	if (c == 'D' || c == 'N')return 4;
	if (c == 'A' || c == 'M')return 2;
	return 6;
}


void refresh(map<int, Node>&m, int id) {
	if (m[id].type == 'P') {
		m[id].value[3] = m[id].value[2];
		return;
	}
	if (m[id].type == 'L') {
		return;
	}
	if (m[id].gateType == 'D') {
		m[id].value[2] = m[id].value[0];
		m[id].value[3] = m[id].value[1];
	}
	if (m[id].gateType == 'A') {
		if (m[id].value[0] == 1 && m[id].value[1] == 1) {
			m[id].value[2] = 1, m[id].value[3] = 1;
		}
		else if (m[id].value[0] == 0 || m[id].value[1] == 0) {
			m[id].value[2] = 0, m[id].value[3] = 0;
		}
	}
	if (m[id].gateType == 'O') {
		if (m[id].value[0] == 1 || m[id].value[1] == 1) {
			m[id].value[2] = 1, m[id].value[3] = 1;
		}
		else if (m[id].value[0] == 0 && m[id].value[1] == 0) {
			m[id].value[2] = 0, m[id].value[3] = 0;
		}
	}
	if (m[id].gateType == 'N') {
		m[id].value[2] = m[id].value[0]==-1 ? -1 : 1- m[id].value[0];
		m[id].value[3] = m[id].value[1]==-1 ? -1 : 1- m[id].value[1];
	}
	if (m[id].gateType == 'M') {
		if (m[id].value[0] == 0)m[id].value[2] = 0;
		if (m[id].value[0] == 1)m[id].value[2] = m[id].value[1];
		if (m[id].value[1] == 0)m[id].value[3] = m[id].value[0] == -1 ? -1 : 1 - m[id].value[0];
		if (m[id].value[1] == 1)m[id].value[3] = 0;
	}
}
void initValueFromOne(map<int, Node>&m, int firstid) //id的节点刷新后,调用此函数刷新后续节点   
{
	queue<int>q; //需要刷新状态的队列
	q.push(firstid);  
	refresh(m, firstid);  
	while (!q.empty()) {
		int id = q.front();
		q.pop();
		int idout1 = m[id].out1;

		if (idout1 > -1) {
			if (m[idout1].in1 == -1) { 
				m[idout1].in1 = id;
			}
			else if (m[idout1].in2 == -1) { 
				m[idout1].in2 = id;
			}
			int x = m[idout1].in1 == id ? 0 : 1;
			bool isFreshed = (m[idout1].value[x] != m[id].value[2]); 
			if (isFreshed) { 
				m[idout1].value[x] = m[id].value[2]; 
				q.push(idout1); 
			}
		}
		int idout2 = m[id].out2;
		
		if (idout2 > -1) {
			if (m[idout2].in1 == -1) { 
				m[idout2].in1 = id;
			}
			else if (m[idout2].in2 == -1) { 
				m[idout2].in2 = id;
			}
			int x = m[idout2].in1 == id ? 0 : 1;
			bool isFreshed = (m[idout2].value[x] != m[id].value[3]);
			if (isFreshed) {
				m[idout2].value[x] = m[id].value[3];
				q.push(idout2);
			}
		}
	}
}
void initValue(map<int, Node>&m, vector<int>powerNodes)
{
	for (auto id : powerNodes)initValueFromOne(m, id);
}

int point(map<int,Node>m, vector<int>powerNodes, vector<int>lightNodes){
	int s = 0;
	for (auto id : lightNodes) {
		if (m[id].value[0] == 1 && m[id].value[1] == 1) { //这个灯是否亮
			if(m[id].isMine)s += 1000;
			else s -= 1000;
		}
		else if (m[id].value[0] == 0 || m[id].value[1] == 0) { //这个灯不可能亮 
			continue;
		}
		else if (m[id].value[0] == 1 || m[id].value[1] == 1) { //这个灯可能亮
			if (m[id].isMine)s += 500;
			else s -= 500;
		}
		else {   //2个-1的未知信号
			if (m[id].isMine)s += 250;
			else s -= 250;
		}
	}
	for (auto mi : m) {
		if (mi.second.type == 'G') {
			if (mi.second.isMine)s -= gatePower(mi.second.gateType);
			else s+= gatePower(mi.second.gateType);
		}
	}
	return s;
}
void setMap(map<int, Node>&m, char t, int id) 
{
	m[id].gateType = t; 
	initValueFromOne(m, id); 
}

pair<int,char> choice(map<int, Node>m, vector<int>powerNodes, vector<int>lightNodes,vector<int>validNodes) {
	int maxPoint = -123456;
	int ansid = 0;
	char anst;
	initValue(m, powerNodes);
	for (auto id : validNodes) {
		for (char t : "DAONM") {
			auto m2 = m;
			setMap(m2, t, id);
			int p = point(m2, powerNodes, lightNodes);
			if (maxPoint < p) {
				maxPoint = p;
				ansid = id;
				anst = t;
			}
			//reback(m, id);  
		}
	}
	return make_pair(ansid, anst);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值