spoj 196 Musketeers(决斗)

黑书中一道例题:决斗https://www.spoj.pl/problems/MUSKET/

书中的分析:

假设需要判断x是否能赢得整场战斗,把环看成链,x点拆成两个,那么编号为x的人能从中胜出的充分必要

条件是他能与自己“相遇”。这样,在连续几个人的链中,只须考虑头尾两个人能否胜利会师,中间的则不予

考虑。设meet[i][j]记录i和j能相遇,能则为true,否则为false,则问题转化为了是否能找到一个k,使得

i 和 k, k和j均能相遇,而 i或j能打败k。

//3463926  	2010-04-04 16:10:26 	superbin	Musketeers	 accepted 	0.03 	 2.7M 	
//技巧将meet加倍,以表示循环的人链
#include <stdio.h>
#include <string.h>
#define NL 110

bool e[NL][NL];
bool meet[NL*2][NL*2];
bool muk[NL];

int main()
{
	int T;
	int n, sum;
	int i, j, k, t;
	char s[NL];
	scanf("%d", &T);
	while (T--) {
		scanf("%d", &n);
		for (i=0; i<n; i++) {
			scanf("%s", s);
			for (j=0; j<n; j++)
				if (s[j]=='1') e[i][j] = 1;
				else e[i][j] = 0;
		}
		memset(muk, 0, sizeof(muk));
		memset(meet, 0, sizeof(meet));				
		for (i=0; i<2*n-1; i++)
			meet[i][i+1] = 1;
		sum = 0;
		for (k=2; k<=n; k++) {
			for (i=0; i+k<2*n; i++) {
				j = i+k;
				int flg = 0;
				for (t=i+1; t<j; t++) {
					if (meet[i][t] && meet[t][j]
						&& (e[i%n][t%n] || e[j%n][t%n])) {
						flg = 1;
						break;
					}
				}
				if (flg) {
					meet[i][j] = 1;
					if (k==n) {
						sum++;
						muk[i] = 1;
					}
				}								
			}
		}
		printf("%d\n", sum);
		for (i=0; i<n; i++) {
			if (muk[i])
				printf("%d\n", i+1);
		}
	}
	return 0;					
}

 

转载于:https://www.cnblogs.com/superbin/archive/2010/04/04/1704398.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值