http://poj.org/problem?id=1691
题目大意:给一个矩形面板,里面分成了多个相邻无重叠的矩形,需要给每个矩形上色。
规定只能从上往下上色,每个矩形上方相连的矩形都上过色才能上色。
问最少的换笔次数。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
struct Node
{
int x1,y1,x2,y2,c;
};
Node c[16];
int map[16][16],rudu[16],use[16],s,n,minn;
bool cmp(Node a,Node b)
{
return a.y1<b.y1;
}
void dfs(int k,int f,int v)
{
int i,vis[16],j;
if(v==n)//矩形全部涂完
if(f<minn)
{
minn=f;
}
for(i=0;i<n;i++)
{
if(rudu[i]==0&&use[i]==0)//入度为0表示矩形上方的矩形均涂色了
{
memset(vis,0,sizeof(vis));//用来记录哪些点被更改,以便回溯
use[i]=1;
for(j=0;j<n;j++)
{
if(map[i][j]==1)
{
vis[j]=1;
map[i][j]=0;
rudu[j]--;
}
}
if(k==-1)//刚开始是没颜色的寻找第一次拿起的颜色
dfs(c[i].c,1,1);
else if(k==c[i].c)//不需要换笔的情况
dfs(k,f,v+1);
else
dfs(c[i].c,f+1,v+1);//换笔的情况
//回溯
use[i]=0;
for(j=0;j<n;j++)
{
if(vis[j]==1)
{
map[i][j]=1;
rudu[j]++;
}
}
}
}
}
int main()
{
int t,i,j;
cin>>t;
while(t--)
{
cin>>n;
memset(rudu,0,sizeof(rudu));
memset(map,0,sizeof(map));
for(i=0;i<n;i++)
cin>>c[i].y1>>c[i].x1>>c[i].y2>>c[i].x2>>c[i].c;
//建图
sort(c,c+n,cmp);
for(i=0;i<n;i++)
for(j=0;j<i;j++)
{
if(c[j].y2==c[i].y1)
{
if(c[j].x1<c[i].x2&&c[j].x2>c[i].x1)
{
map[j][i]=1;//表示要涂矩形i需要先涂矩形j
rudu[i]++;
}
}
}
minn=22;
memset(use,0,sizeof(use));
dfs(-1,0,0);
cout<<minn<<endl;
}
return 0;
}