首页 > 其他分享 >P2482 [SDOI2010] 猪国杀

P2482 [SDOI2010] 猪国杀

时间:2022-10-16 14:46:01浏览次数:102  
标签:猪国 int id2 id SDOI2010 pigs && type P2482

P2482 [SDOI2010] 猪国杀

AC于2022年8月9日,代码写了一个晚上

点击查看代码
#include <stdio.h>
#include <string.h>
const int N = 15, M = 2005;
struct Pig {
	char type; // 类型
	bool showed; // 暴露身份
	bool fan_likely; // 被认为是类反猪
	bool have_weapon; // 有猪哥连弩
	bool alive; // 活着
	int tili; // 体力
	int card_count; // 拿过的牌的个数
	char cards[M]; // 拿过的牌, 若用过,标记为X
	bool Zhong() { return showed && type == 'Z'; } // 是否跳忠
	bool Fan() { return showed && type == 'F'; } // 是否跳反
} pigs[N];
int n, m, card_index;
int FanPigCount; // 活着的反猪个数
char remain_cards[M];
char winner;
// 读入
void input() {
	scanf("%d%d", &n, &m);
	char tp[3], card[2];
	for(int i = 1; i <= n; i ++) {
		scanf("%s", tp);
		pigs[i].type = *tp; // 猪的类型
		pigs[i].card_count = 4; // 猪的牌
		pigs[i].fan_likely = false; // 不是类反猪
		pigs[i].have_weapon = false; // 没有武器
		pigs[i].showed = i == 1; // 是否暴露
		pigs[i].alive = true; // 还活着
		pigs[i].tili = 4; // 初始体力
		if(*tp == 'F') FanPigCount ++;
		for(int j = 1; j <= 4; j ++)
			scanf("%s", card), pigs[i].cards[j] = *card; // 原始的牌
	}
	for(int i = 1; i <= m; i ++)
		scanf("%s", card), remain_cards[i] = *card; // 牌堆
}
// 拿一张牌
void get_a_card(int id) {
	if(card_index != m) card_index ++; // 没有用完
	pigs[id].cards[++ pigs[id].card_count] = remain_cards[card_index];
}
int next_alive(int id) {
	for(int id2 = id + 1; id2 != id; id2 ++, id2 > n && (id2 = 1))
		if(pigs[id2].alive) return id2;
	return 0;
}
// 体力变为0时的处理
void killed(int id, int killer) {
	// 先判断是否有桃子P(共性1)
	for(int i = 1; i <= pigs[id].card_count; i ++) // 枚举是否有桃子
		if(pigs[id].cards[i] == 'P') {
			pigs[id].tili ++; // 体力++
			pigs[id].cards[i] = 'X'; // 用过了
			if(pigs[id].tili > 0) return; // 活了!
		}
	pigs[id].alive = false; // 死了
	if(pigs[id].type == 'M') { // 主猪死亡
		winner = 'F'; // 反猪胜利
	} else if(pigs[id].type == 'Z') { // 忠猪死亡
		if(pigs[killer].type == 'M') { // 主猪干的
			pigs[killer].card_count = 0; // 牌没了
			pigs[killer].have_weapon = false; // 装备没了
		}
	} else if(pigs[id].type == 'F') { // 反猪死亡
		FanPigCount --;
		if(FanPigCount == 0) // 反猪全完
			winner = 'M'; // 主猪胜利
		else get_a_card(killer), get_a_card(killer), get_a_card(killer); // 拿3张牌
	}
}
// 吃桃子P, 共性1:吃掉
bool use_P(int id) {
	if(pigs[id].tili < 4) {
		pigs[id].tili ++;
		return true; // 用了桃子
	} return false;
}
// 闪D 若没有,则体力--
void use_D(int id) {
	for(int i = 1; i <= pigs[id].card_count; i ++)
		if(pigs[id].cards[i] == 'D') {
			pigs[id].cards[i] = 'X'; // 被用了
			return;
		}
	pigs[id].tili --;
}
// 杀K, 只能杀下一只猪
bool use_K(int id) {
	if(pigs[id].type == 'M') { // 主猪用杀
		int id2 = next_alive(id);
		if(pigs[id2].Fan() || pigs[id2].fan_likely) { // 反猪或类反猪
			use_D(id2); // 用闪回击
			if(pigs[id2].tili <= 0) killed(id2, id); // 被杀了
			return true; // 用了杀
		}
	} else if(pigs[id].type == 'Z') { // 忠猪
		int id2 = next_alive(id);
		if(pigs[id2].Fan()) {
			pigs[id].showed = true, pigs[id].fan_likely = false; // 暴露身份
			use_D(id2);
			if(pigs[id2].tili <= 0) killed(id2, id);
			return true;
		}
	} else if(pigs[id].type == 'F') { // 反猪
		int id2 = next_alive(id);
		if(pigs[id2].Zhong() || pigs[id2].type == 'M') { // 主猪或忠猪
			pigs[id].showed = true, pigs[id].fan_likely = false; // 暴露身份
			use_D(id2);
			if(pigs[id2].tili <= 0) killed(id2, id);
			return true;
		}
	}
	return false;
}
// 无懈可击, id表示使用锦囊的猪, target 表示目标方 1表示主猪方, 2表示反猪方
bool use_J(int id, int target) {
	int id2 = id; // 注意: 自己也可以用无懈可击
	do {
		if(pigs[id2].alive) {
			if((pigs[id2].type == 'F' && target == 2) || (pigs[id2].type != 'F' && target == 1)) {
				// 反猪帮反猪 或 忠猪帮主猪
				for(int i = 1; i <= pigs[id2].card_count; i ++)
					if(pigs[id2].cards[i] == 'J') {
						pigs[id2].showed = true, pigs[id2].fan_likely = false; // 暴露身份
						pigs[id2].cards[i] = 'X'; // 被用了
						return !use_J(id2, 3 - target); // 轮到对方无懈可击
					}
			}
		}
		id2 ++, id2 > n && (id2 = 1);
	} while(id2 != id);
	return false; // 用不了
}
void swap(int &x, int &y) { static int z; z = x, x = y, y = z; }
void fight(int id, int id2) {
	if(pigs[id].type == 'M' && pigs[id2].type == 'Z') { // 主猪和忠猪决斗: 忠猪绝不出牌
		pigs[id2].tili --;
		if(pigs[id2].tili <= 0) killed(id2, id);
	} else { // 不遗余力出牌
		int now = id2, other = id; // 现在出牌的人, 另一个人
		while(true) {
			bool found = false; // 找到杀并使用
			for(int i = 1; i <= pigs[now].card_count; i ++)
				if(pigs[now].cards[i] == 'K') {
					pigs[now].cards[i] = 'X';
					found = true;
					break;
				}
			if(found) swap(now, other); // 轮流出牌
			else {
				pigs[now].tili --;
				if(pigs[now].tili <= 0) killed(now, other); // 被杀了
				return;
			}
		}
	}
}
// 决斗F
bool use_F(int id) {
	if(pigs[id].type == 'M') { // 主猪打反猪与类反猪
		for(int id2 = id + 1; id2 != id; id2 ++, id2 > n && (id2 = 1))
			if(pigs[id2].alive && (pigs[id2].Fan() || pigs[id2].fan_likely)) {
				if(!pigs[id2].showed || !use_J(id, 2)) fight(id, id2); // fight:打架
				return true; // 注意: 没有暴露身份的对手的不能用无懈可击
			}
	} else if(pigs[id].type == 'Z') { // 忠猪找反猪
		for(int id2 = id + 1; id2 != id; id2 ++, id2 > n && (id2 = 1))
			if(pigs[id2].alive && pigs[id2].Fan()) {
				if(!pigs[id2].showed || !use_J(id, 2)) fight(id, id2);
				pigs[id].showed = true; // 身份暴露
				return true;
			}
	} else if(pigs[id].type == 'F') { // 反猪找主猪
		if(!use_J(id, 1)) fight(id, 1); // 主猪身份明确, 可以使用无懈可击
		pigs[id].showed = true; // 身份暴露
		return true;
	}
	return false;
}
// 南猪入侵
bool use_N(int id) {
	for(int id2 = id + 1; id2 != id; id2 ++, id2 > n && (id2 = 1))
		if(pigs[id2].alive) {
			if(pigs[id2].showed && use_J(id, pigs[id2].type == 'F' ? 2 : 1)) continue; // 被无懈可击了
			bool hurt = true; // 对id2产生伤害
			for(int i = 1; i <= pigs[id2].card_count; i ++)
				if(pigs[id2].cards[i] == 'K') {
					pigs[id2].cards[i] = 'X';
					hurt = false;
					break;
				}
			if(hurt) { // 造成伤害
				pigs[id2].tili --;
				if(pigs[id2].tili <= 0) killed(id2, id); // 被杀了
				if(winner) return true; // 立即退出
				if(id2 == 1 && !pigs[id].showed) pigs[id].fan_likely = true; // 主猪被未表明身份的伤害:类反猪
			}
		}
	return true;
}
bool use_W(int id) {
	for(int id2 = id + 1; id2 != id; id2 ++, id2 > n && (id2 = 1))
		if(pigs[id2].alive) {
			if(pigs[id2].showed && use_J(id, pigs[id2].type == 'F' ? 2 : 1)) continue; // 被无懈可击了
			bool hurt = true; // 对id2产生伤害
			for(int i = 1; i <= pigs[id2].card_count; i ++)
				if(pigs[id2].cards[i] == 'D') {
					pigs[id2].cards[i] = 'X';
					hurt = false;
					break;
				}
			if(hurt) { // 造成伤害
				pigs[id2].tili --;
				if(pigs[id2].tili <= 0) killed(id2, id); // 被杀了
				if(winner) return true; // 立即退出
				if(id2 == 1 && !pigs[id].showed) pigs[id].fan_likely = true; // 主猪被未表明身份的伤害:类反猪
			}
		}
	return true;
}
int main() {
	input();
	while(true) for(int id = 1; id <= n; id ++) if(pigs[id].alive) {
		get_a_card(id), get_a_card(id); // 摸牌
		bool can_use_K = true;
		for(int i = 1; i <= pigs[id].card_count; i ++) {
			if(pigs[id].cards[i] == 'X') continue;
			bool used_card = false; // 是否使用牌
			if(pigs[id].cards[i] == 'P') used_card = use_P(id); // 能够吃桃子
			else if(pigs[id].cards[i] == 'K') {
				if(pigs[id].have_weapon) can_use_K = true; // 有武器: 能够用任意次杀
				if(can_use_K) {
					used_card = use_K(id); // 杀
					if(used_card) can_use_K = false; // 用了
				}
			} else if(pigs[id].cards[i] == 'F') used_card = use_F(id);
			else if(pigs[id].cards[i] == 'N') used_card = use_N(id);
			else if(pigs[id].cards[i] == 'W') used_card = use_W(id);
			else if(pigs[id].cards[i] == 'Z') used_card = pigs[id].have_weapon = true; // 猪哥连弩
			if(used_card) pigs[id].cards[i] = 'X', i = 0; // 用过了, i=0是因为前面的牌可能可以用
			if(!pigs[id].alive) break; // 猪死了, 完
			if(winner) goto GAME_OVER; // 立即退出
		}
	}
	GAME_OVER: printf("%cP\n", winner);
	for(int id = 1; id <= n; id ++)
		if(pigs[id].alive) {
			for(int i = 1; i <= pigs[id].card_count; i ++)
				if(pigs[id].cards[i] != 'X') printf("%c ", pigs[id].cards[i]);
			putchar(10);
		} else puts("DEAD");
	return 0;
}

标签:猪国,int,id2,id,SDOI2010,pigs,&&,type,P2482
From: https://www.cnblogs.com/azzc/p/16796197.html

相关文章

  • 挑战猪国杀
    码了一个上午,代码存到hz服务器上面了,结果因为服务器里有人删了我东西,导致我码没了,一个上午白干了......然后下午从头开始.码了一整个下午,终于把主体结构干完了.一共276......
  • 猪国杀
    先放码#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<set>#defineSakuraint#defineReregisterint#define_putchar......
  • 一天过去了, 猪国杀结束了
    %%%%%%%%%%%%%%%%%%chen_jr四个小时就切了猪国杀%%%%%%%%%%%%%而我是什么fengwufeiwu然后就是与世俗同流合污的部分......
  • 关于猪国杀
    从今天下午开始看题于2022.10.419:26:23在\(loj\)\(ac\)没有大改,没有重构,框架一遍过下面是原版代码code#include<bits/stdc++.h>usingnamespacestd;#defineM......
  • P2467 [SDOI2010]地精部落
    P2467[SDOI2010]地精部落题目传送门题目大意:略题目分析:首先一眼可以知道这个是个计数类的问题,我们可以考虑使用组合数学和\(dp\),由于题目让我们求奇数项都高于或低......
  • [挑战记录]猪国杀
    觉得没有做过猪国杀的人生是不完整的!于是决定开肝(2022-09-2218:45吃着葡萄欣赏“人走机子开”开始答题19:29看错一次题目(必须从左边开始摸牌)19:54又看错一次题目(......