poj 1691 Painting A Board (拓扑排序+dfs)

题目链接:http://poj.org/problem?id=1691

题目大意:给你n个小矩形,可以一个大矩形。给这n个小矩形涂色,涂色的要求是:只有位于它上方的并且和它邻接的小矩形涂完了色,它才能涂色。(很明显想到拓扑排序)

用刷子给n个矩形涂色,刷子一次可以给多个符合涂色要求的相同颜色的矩形涂色。当颜色不同时,需要换刷子。问最少需要换多少次刷子?

题目的输入:样例个数,每个样例的小矩形的个数,以及每个小矩形的左上角,右下角的坐标,给该矩形涂的哪种颜色。

题目的输出:需要换刷子的最少次数。

思路:先构建图。然后用深搜和拓扑排序的思想,解决问题。

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
/*
先拓扑排序,再dfs枚举
*/
struct Point {
	int x, y;
};
struct Node {
	Point start, end;
	int kind;
};
Node node[110];
vector<int> vect[110];
int indegree[110];
int visit[110];
int mmax, n;
void Dfs(int x, int num) {
	int i, t;
	if(num > n) return;
	for(i=0; i<n; i++)
		if(visit[i] == 0) break;
	if(i == n) {
	    //printf("num = %d\n", num);
	    //printf("----------------\n");
		if(num < mmax) mmax = num;
		return;
	}
	for(i=0; i<vect[x].size(); i++) {
		t = vect[x][i];
		indegree[t] --;
	}
	for(i=0; i<n; i++)
		if(indegree[i] == 0 && visit[i] == 0) {
		    visit[i] = 1;
			if(node[i].kind != node[x].kind) Dfs(i, num+1);
			else Dfs(i, num);
			//printf("kind1 = %d, kind2 = %d, node = %d, num = %d\n", node[x].kind, node[i].kind, i, num);
			visit[i] = 0;
		}
	for(i=0; i<vect[x].size(); i++) {
		t = vect[x][i];
		indegree[t] ++;
	}
}
/*void Print() {
    int i;
    for(i=0; i<n; i++) printf("%d\t",indegree[i]);
    printf("\n");
}*/
int main() {
	int t, i, j;
	//freopen("in.txt", "r", stdin);
	scanf("%d", &t);
	while(t--) {
		scanf("%d", &n);
		for(i=0; i<n; i++) {
			vect[i].clear();
			scanf("%d%d%d%d%d", &node[i].start.y,&node[i].start.x,&node[i].end.y,&node[i].end.x,&node[i].kind);
		}
		//建图
		for(i=0; i<n; i++) {
			indegree[i] = 0;
			for(j=0; j<n; j++) {
				if(node[j].end.y == node[i].start.y && node[i].end.x - node[j].start.x > 0 && node[j].end.x - node[i].start.x > 0) {
					vect[j].push_back(i);
					indegree[i] ++;
				}
			}
		}
		//Print();
		//dfs
		mmax = n;
		memset(visit, 0, sizeof(visit));
		for(i=0; i<n; i++) {
			if(indegree[i] == 0) {
				visit[i] = 1;
				//printf("Go:node=%d, num = 1\n", i);
				Dfs(i, 1);
				visit[i] = 0;
			}
		}
		printf("%d\n", mmax);
	}
	return 0;
}

总结:这个题目首先没有想到拓扑排序,而且在写dfs的时候,里面的

for(i=0; i<n; i++)
		if(indegree[i] == 0 && visit[i] == 0) {
		    visit[i] = 1;
			if(node[i].kind != node[x].kind) Dfs(i, num+1);
			else Dfs(i, num);
			//printf("kind1 = %d, kind2 = %d, node = %d, num = %d\n", node[x].kind, node[i].kind, i, num);
			visit[i] = 0;
		}
这段代码,原先是这样写的:

for(i=0; i<n; i++)
		if(indegree[i] == 0 && visit[i] == 0) {
			if(node[i].kind != node[x].kind)  num++;
                         visit[i] = 1;
			Dfs(i, num);
			//printf("kind1 = %d, kind2 = %d, node = %d, num = %d\n", node[x].kind, node[i].kind, i, num);
			visit[i] = 0;
		}
自己调了很久才调出来。看来对深搜还是理解的不够深。看后面的讨论这题可以用状态压缩的dp,看来自己......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值