poj 1691 Painting A Board 拓扑序+dfs

题意:

一个木板上被分成了很多区域,每个区域要涂上一种特定的颜色,当涂一个区域的时候,它上方与它有重合部分的区域必须之前要涂好。求最少需要拿几次画笔(拿一次画笔可以涂颜色相同的多个区域)。

分析:

上方与它有重合部分的区域必须之前要涂好这个限制可以用拓扑序来描述,每次涂有很多种可以涂的颜色,dfs就可以了。dfs的状态空间维数定为拿笔的次数,每次枚举可以涂的颜色。要注意的是dfs过程中要慎用全局变量。。否则每个维度需枚举的东西被下一维改了就跪了。。。

代码:

//poj 1691
//sep9
#include <iostream>
using namespace std;
int n,col_max,ans;
int g[32][32];
int d[32];
int colored[32];

struct P
{
	int x1,y1,x2,y2,col;
}p[32];

void dfs(int color_used,int times)
{
	if(color_used>=n){
		ans=times;
		return ;
	}
	if(times>=ans)
		return ;
	int i,j,k,col,col_num,t=0;
	int tmp1[32];
	int tmp2[32];
	int try_col[32];
	int in_set[32];
	memset(try_col,0,sizeof(try_col));
	memset(in_set,0,sizeof(in_set));
	for(i=1;i<=n;++i)
		if(!d[i]&&!colored[i]&&!in_set[p[i].col]){
			try_col[++t]=p[i].col;
			in_set[p[i].col]=1;
		}
	for(i=1;i<=t;++i){
		col=try_col[i];
		col_num=0;
		memcpy(tmp1,colored,sizeof(colored));
		memcpy(tmp2,d,sizeof(d));
		while(1){
			int find;
			for(find=0,j=1;j<=n;++j)
				if(!d[j]&&!colored[j]&&p[j].col==col){
					colored[j]=1;
					find=1;
					++col_num;
					for(k=1;k<=n;++k)
						if(g[j][k]==1&&d[k])
							--d[k];
				}
			if(!find)
				break;
		}
		dfs(color_used+col_num,times+1);
		memcpy(colored,tmp1,sizeof(tmp1));
		memcpy(d,tmp2,sizeof(tmp2));
	}
	return ;
}

int main()
{
	int cases,i,j;
	scanf("%d",&cases);
	while(cases--){
		scanf("%d",&n);
		memset(g,0,sizeof(g));
		memset(d,0,sizeof(d));
		memset(colored,0,sizeof(colored));
		col_max=0;
		for(i=1;i<=n;++i){
			scanf("%d%d%d%d%d",&p[i].x1,&p[i].y1,&p[i].x2,&p[i].y2,&p[i].col);
			col_max=max(col_max,p[i].col);
		}
		for(i=1;i<=n;++i)
			for(j=1;j<=n;++j)
				if(i!=j)
					if(p[i].x2==p[j].x1)
						if(!(p[i].y2<=p[j].y1||p[i].y1>=p[j].y2)){
							g[i][j]=1;
							++d[j];
						}
		ans=INT_MAX;
		dfs(0,0);
		printf("%d\n",ans);
	}
	return 0;
} 
时间: 2025-01-22 01:25:43

poj 1691 Painting A Board 拓扑序+dfs的相关文章

POJ 1691 Painting A Board(DFS)

链接 题意 : 看了好长时间终于看懂题目了,将一个大矩形划分成若干小矩形,告诉你每个小矩形的左上角那个点和右下角那个点的坐标,告诉你这个小矩形要涂的颜色,每个颜色对应一个刷子,问你最少要使用几次刷子.因为你要刷一个矩形之前,必须把这个矩形上方与之直接相邻的所有矩形先刷掉才能刷这个,如果你先用了红色的刷子,然后又用了蓝色的刷子,最后又用了红色的刷子,这算是3次使用而不是两次,样例中,用红色刷B所以D也可以刷了,用蓝色先刷A,然后可以刷C,因为B刷了所以E也可以刷了,最后换刷子把剩下的刷掉,总共三次

POJ 1691 Painting A Board

题目大意: 墙上有一块区域被分成了n个矩形,每个矩形要涂上各自的颜色.为了保证完美要求这一块区域可以进行涂色的条件是它上方的所有区域都已经涂好颜色,这样就不会有后续的操作影响这块区域的颜色.但是如果两块区域颜色不同就要换涂颜色用的刷子.问最少需要换几次. 解题思路: 区域涂色的大体次序是由拓扑排序决定的,当有多个区域在同一层次时需要枚举这些区域来保证换刷子的次数最小. 下面是代码: #include <stdio.h> #include <stdlib.h> struct node

[poj 1691] Painting A Board dfs+拓扑排序

Painting A Board Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 3611 Accepted: 1795 Description The CE digital company has built an Automatic Painting Machine (APM) to paint a flat board fully covered by adjacent non-overlapping rectangle

poj - 1691 - Painting A Board(状态压缩dp)

题意:N(1 <= N <= 15)个矩形,每个矩形要涂上指定的颜色C(1 <= C <= 20),如果给一个矩形涂色,那么与它相邻的上方矩形必须已经涂色,问最少要取几次画笔. 题目链接:http://poj.org/problem?id=1691 -->>状态:dp[S][color] 表示达到状态 S 且最后一次涂色为 color 时的最小取画笔数 状态转移方程:dp[S][color] = min(dp[S][color], dp[sub][i]); 或者 dp[

POJ - 1691 Painting A Board (状态压缩 + 暴力)

题目大意:要将一个大矩形內的所有小矩形涂色,涂色要求,只有该矩形上面的所有矩形都涂色了才可以涂该颜色,换一种填涂的颜色就要花费一点体力值,问填涂完需要花费的最小体力值 解题思路:先处理一下填涂该矩形的前提条件,我用了一个can数组表示填涂该矩形时要满足的状态量 用dp[color][state]表示当前用的颜色是color,填涂的状态为state时所用的最少体力值 然后暴力得出转换和结果 #include<cstdio> #include<cstring> #include<

POJ 题目1691 Painting A Board(DFS)

Painting A Board Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3471   Accepted: 1723 Description The CE digital company has built an Automatic Painting Machine (APM) to paint a flat board fully covered by adjacent non-overlapping recta

[BZOJ 1103][POI 2007]大都市(DFS求拓扑序+树状数组)

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1103 题目大意:给你一个树,刚开始所有树边边权均为1,不断地将其中的某些边边权改为0,其间问你某个点到根节点之间路径上的边权和. 此题和POJ的Apple Tree很相近... 首先DFS生成整棵树的拓扑序,DFS时每个结点i进入的时间l[i]和离开的时间r[i],然后对每次更改操作,维护树状数组即可. #include <iostream> #include <stdi

poj 1270 Following Orders(拓扑排序+dfs)

大致题意:每个样例包含两行,第一行输入n个字符,可能是无序的.第二行输入成对的a b,代表a要在b前面.输出所有的符合这样的序列. 思路:很明显的拓扑排序.要输出所有的序列,那么就从入度为0的点进行dfs,每次选择一个入度为0的点,加入输出序列并把与它相邻的点的入度减一.dfs结束后要把状态再改回来. #include <stdio.h> #include <algorithm> #include <set> #include <map> #include

UVA10305 拓扑序

题意:给出多个任务,以及一系列任务的关系表示某个任务必须在某个任务前完成,问一个合理的任务完成顺序 拓扑序的裸题,一开始用大白书的写法,后来发现并不好用,就换了BFS又A了一遍. 原: 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 const int maxm=105; 6 7 int vis[maxm],topo[maxm],t; 8 in