【DG特长生2015 T3】糊涂的教授

糊涂的教授

题目链接:None

题目大意

有一些矩阵,然后又有一些数字,你要把数字和矩阵一一对应,使得数字在对于的矩阵里面。
如果有多重对应方法或无法对于就输出 None,否则输出对应方法。

思路

它是有点拓扑的感觉,反正你就不停地到能直接对应的关系。
(一个点只在一个矩阵里面或一个矩阵里面只有一个点)

然后就一直模拟。

(不过后来说上面的两种关系只用挑一种做就可以了,因为另一种其实就是反方向做)

代码

#include<cstdio>

using namespace std;

int n, x1[31], y1[31], x2[31], y2[31], x, y;
int have_point[31][31], in_board[31][31];
int real_have[31], real_in[31], dy[31];
bool do_point[31], do_board[31];

int main() {
//	freopen("jiaoshou.in", "r", stdin);
//	freopen("jiaoshou.out", "w", stdout);
	
	scanf("%d", &n);
	
	for (int i = 1; i <= n; i++) {
		scanf("%d %d %d %d", &x1[i], &x2[i], &y1[i], &y2[i]);
	}
	
	for (int i = 1; i <= n; i++) {//记录一个点在以多个板里面,一个板里面有多少个点
		scanf("%d %d", &x, &y);
		for (int j = 1; j <= n; j++) {
			if (x >= x1[j] && x <= x2[j] && y >= y1[j] && y <= y2[j]) {
				have_point[j][++have_point[j][0]] = i;
				in_board[i][++in_board[i][0]] = j;
			}
		}
		if (!in_board[i][0]) {
			printf("None");
			return 0;
		}
	}
	
	for (int i = 1; i <= n; i++) {
		real_have[i] = have_point[i][0];
		real_in[i] = in_board[i][0]; 
	}
	
	for (int times = 1; times <= n; times++) {
		bool yes = 0;
		int cho = -1;
		for (int i = 1; i <= n; i++)
			if (!do_board[i]) {//找板里面只有一个点的
				if (real_have[i] == 0) {//这个板里面没有点,不能一一对应
					printf("None");
					return 0;
				}
				if (real_have[i] == 1) {
					yes = 1;
					cho = i;
				}
			}
		if (yes) {
			for (int i = 1; i <= n; i++)
				if (!do_point[i]) {
					if (real_in[i] == 0) {//先确认没有点不在板里面
						printf("None");
						return 0;
					}
				}
			do_board[cho] = 1;
			for (int i = 1; i <= have_point[cho][0]; i++)//将对应的板和点抹去
				if (!do_point[have_point[cho][i]]) {
					do_point[have_point[cho][i]] = 1;
					dy[cho] = have_point[cho][i];
					for (int j = 1; j <= in_board[have_point[cho][i]][0]; j++)
						if (!do_board[in_board[have_point[cho][i]][j]]) real_have[in_board[have_point[cho][i]][j]]--;
					break;
				}
		}
		if (!yes) {
			for (int i = 1; i <= n; i++)
				if (!do_point[i]) {//找点只在一个板里面的
					if (real_in[i] == 0) {//点不在任何板里面,不能一一对应
						printf("None");
						return 0;
					}
					if (real_in[i] == 1) {
						yes = 1;
						cho = i;
					}
				}
			if (yes) {
				do_point[cho] = 1;
				for (int i = 1; i <= in_board[cho][0]; i++)//抹去板和点
					if (!do_board[in_board[cho][i]]) {
						do_board[in_board[cho][i]] = 1;
						dy[in_board[cho][i]] = cho;
						for (int j = 1; j <= have_point[in_board[cho][i]][0]; j++)
							if (!do_point[have_point[in_board[cho][i]][j]]) real_in[have_point[in_board[cho][i]][j]]--;
						break;
					}
			}
		}
		
		if (!yes) {//找不到能继续确定的
			printf("None");
			return 0;
		}
	}
	
	for (int i = 1; i <= n; i++) {//输出
		printf("%c %d\n", i + 'A' - 1, dy[i]);
	}
	
	fclose(stdin);
	fclose(stdout);
	
	return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值