poj 2858

#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
#include<cstring>

using namespace std;

const char s[6]="START";
const char e[4]="END";
const char ee[11]="ENDOFINPUT";
char order[15];
int m[5][5];
int g[10][10];
bool visit[10];
int rec[10];
const int possible[4][4][4]={{{1},{1,2},{2,3},{3}},{{1,4},{1,2,4,5},{2,3,5,6},{3.6}},{{4,7},{4,5,7,8},{5,6,8,9},{6,9}},{{7},{7,8},{8,9},{9}}};
int main(){
	int i,j,k;
	while(scanf("%s",order)!=EOF){
		if(strcmp(ee,order)==0)
			break;
		memset(m,0,sizeof(m));
		memset(g,0,sizeof(g));
		memset(rec,0,sizeof(rec));
		memset(visit,0,sizeof(visit));
		for(i = 0; i < 4; ++i){
			for(j = 0; j < 4; ++j){
				scanf("%d",m[i]+j);
			}
		}
		int tmp,cur;
		for(i = 0; i < 4; ++i){
			for(j = 0; j < 4; ++j){
				//m[i][j]依次为1,2,...,9的起点
				cur = m[i][j];
				for(k = 0; k < 4; ++k){
					tmp = possible[i][j][k];
					if(tmp && tmp != cur){
						if(g[tmp][cur] == 0)
							++rec[cur];
						g[tmp][cur] = 1;
					}
				}
			}
		}
		scanf("%s",order);
		int total = 9;
		bool isok = true;
	    while(total){
			for(i = 1; i < 10; ++i){
				if((!visit[i])&&(rec[i]==0)){
					break;
				}
			}
			if(i == 10){
				isok = false;
				break;
			}
			visit[i] = 1;
			--total;
			for(j = 0; j < 10; ++j){
				if(g[i][j]){
					--rec[j];
				}
			}	
		}
		if(isok){
			printf("THESE WINDOWS ARE CLEAN\n");
		}
		else{
			printf("THESE WINDOWS ARE BROKEN\n");
		}
	}
	return 0;
}

思路:将4x4的格子中每个位置可能出现的数字列出来,存在possible数组中,然后对每个位置,取现在屏幕上的数字,说明这个数字把在这个位置其它可能出现的数字覆盖了(也就是这块2x2的格子把其余可能覆盖这个位置的2x2的格子给覆盖了),那么就在两者之间建一条有向边(注意不要建立重复边),然后增加边终点的入度,如果可以拓扑排序,说明屏幕是clean,否则是broken~


难点:1.建立图论模型 2.不要建立重复边 3.想到遍历每个位置可能出现的数字

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值