poj1691 Painting A Board

 1 #include<cstring>

 2 #include<iostream>

 3 using namespace std;

 4 struct node{

 5     int x1,y1,x2,y2,color;

 6 }G[15];

 7 int n,ans,deg[15];//n表区域的个数,ans存储最终结果,deg存储拓扑图中各点的入度 

 8 bool vis[15],m[15][15];//vis用于标记是否访问过,m表示各点之间的联系 

 9 void buildG()//建立拓扑图,用于确定优先级 

10 {

11     for(int i=0;i<n;++i)

12         for(int j=0;j<n;++j)

13             if(G[i].y2==G[j].y1&&!(G[i].x2<G[j].x1||G[j].x2<G[i].x1)){

14                 m[i][j]=1;//建立关系网 

15                 deg[j]++;//入度+1 

16             }

17 }

18 void dfs(int dep,int cnt,int curC)//深度优先搜索 

19 {

20     if(cnt>=ans) return;//剪枝,假如当前取画笔次数已大于之前结果,直接返回 

21     if(dep==n){//到达解答树目标状态,保存ans值,因前面有cnt>=ans时退出,所以当前cnt较小 

22         ans=cnt;

23         return;

24     }

25     int i,j;

26     for(i=0;i<n;++i)

27         if(!deg[i]&&!vis[i]){//找入度为0且还未着色的点开始, 

28             vis[i]=1;

29             for(j=0;j<n;++j)

30                 if(m[i][j])

31                     deg[j]--;//子节点入度减一 

32             if(G[i].color==curC) dfs(dep+1,cnt,curC);//与当前颜色符合,只需往下遍历 

33             else dfs(dep+1,cnt+1,G[i].color);//否则,换画笔及颜色    

34             for(j=0;j<n;++j)

35                 if(m[i][j])

36                     deg[j]++;//递归结束后,还原其初始状态 

37             vis[i]=0;//标志取消 

38         }

39 }

40 int main()

41 {

42     int i,j,T;

43     cin>>T;

44     while(T--)

45     {

46         cin>>n;

47         for(i=0;i<n;++i)

48             cin>>G[i].y1>>G[i].x1>>G[i].y2>>G[i].x2>>G[i].color;

49         memset(m,0,sizeof(m));

50         memset(deg,0,sizeof(deg));

51         buildG();

52         ans=15;

53         dfs(0,0,0);//都从0开始 

54         cout<<ans<<endl;

55     }

56     return 0;

57 }

//DFS+拓扑排序

你可能感兴趣的:(paint)