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+拓扑排序

posted on 2012-08-17 21:02  小花熊  阅读(419)  评论(0编辑  收藏  举报

导航