其实这道题一开始没有什么思路,是别人带了节奏之后我一问是DFS加拓扑,上下相邻的连一条边(由上指向下)瞬间就明白了:
代码也很简单,我这么粗心的家伙都1A,就不多解释了,直接上代码:
/*Problem: 1691 User: Burglar
Memory: 656K Time: 32MS
Language: G++ Result: Accepted
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#define MAXN 20
#define INF 10000000
using namespace std;
struct Matrix
{
int lx,ly;//左上角的左边
int rx,ry;//右上角的坐标
int color;//矩阵颜色
}matrix[MAXN];
int n,degree[MAXN],path[MAXN][MAXN];//TOP数组
int judge[MAXN];//在DFS是标记是否已经涂过颜色
int min_ans;//答案
bool have_path(Matrix a,Matrix b)//用于在TOP构图时判断矩阵a是否在矩阵b下方并且相邻
{
if(a.ly==0) return false;
else if(a.ly==b.ry)
{
if(a.lx>=b.rx||a.rx<=b.lx) return false;
else
return true;
}
else
return false;
}
int Min(int a,int b)
{
if(a<b) return a;
else
return b;
}
void dfs(int now_color,int time,int done)//DFS枚举答案,没什么需要多说的;三个参数从左至右的意义依次是:现在机器人手中的刷子颜色;换刷子的次数;已经涂完的矩阵数;
{
if(time>min_ans) return;
if(done==n)
{
min_ans=Min(min_ans,time);
return;
}
else
{
for(int i=0;i<n;i++)
{
if(degree[i]==0&&judge[i]==0)
{
judge[i]=1;
for(int j=0;j<n;j++)
{
if(j==i) continue;
else
{
if(path[i][j])
{
degree[j]--;
}
}
}
if(now_color==matrix[i].color) dfs(now_color,time,done+1);
else
dfs(matrix[i].color,time+1,done+1);
for(int j=0;j<n;j++)
{
if(j==i) continue;
else
{
if(path[i][j])
{
degree[j]++;
}
}
}
judge[i]=0;
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
//注意初始化
memset(matrix,0,sizeof(matrix));
memset(degree,0,sizeof(degree));
memset(judge,0,sizeof(judge));
memset(path,0,sizeof(path));
min_ans=INF;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d%d%d%d%d",&matrix[i].ly,&matrix[i].lx,&matrix[i].ry,&matrix[i].rx,&matrix[i].color);
}
for(int i=0;i<n;i++)//TOP构图
{
for(int j=0;j<n;j++)
{
if(i==j) continue;
else
{
if(have_path(matrix[i],matrix[j]))
{
path[j][i]=1;
degree[i]++;
}
}
}
}
dfs(0,0,0);
printf("%d\n",min_ans);
}
return 0;
}