http://poj.org/problem?id=1691
/*
题解:
将每个矩形看成一个点,点A在点B的上方 则b的入度加1,进行拓扑构图 标记 ,每次搜索时搜入读为零的点
构图时少考虑的一种情况 wa 汗。。。。。。。
*/
#include<stdio.h>
#include<string.h>
#define max 999999
#define maxn 2000
struct node
{
int xl,yl,xr,yr;
int c;
}p[maxn];
int map[20][20],in[20],n,ans,vis[20];
void build()
{
int i,j;
memset(map,0,sizeof(map));
memset(in,0,sizeof(in));
memset(vis,0,sizeof(vis));
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(i==j)continue;
if(p[i].yr==p[j].yl&&!(p[j].xl>=p[i].xr||p[j].xr<=p[i].xl))//连边条件
{
map[i][j]=1;
in[j]++;
}
}
}
}
void DFS(int pre,int num,int sum)
{
if(ans==1)return ;
int i,j;
if(num==n)
{
if(ans>sum)ans=sum;
return ;
}
for(i=0;i<n;i++)
{
if(in[i]==0&&!vis[i])
{
vis[i]=1;
for(j=0;j<n;j++)
{
if(map[i][j])in[j]--;
}
if(p[i].c==pre)
DFS(p[i].c,num+1,sum);
else DFS(p[i].c,num+1,sum+1);
vis[i]=0;
for(j=0;j<n;j++)
{
if(map[i][j])in[j]++;
}
}
}
}
int main()
{
int t,i,j;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d%d%d%d",&p[i].yl,&p[i].xl,&p[i].yr,&p[i].xr,&p[i].c);
}
build();
/*for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
printf("%d ",map[i][j]);
printf("\n");
}*/
//for(i=0;i<n;i++)printf("%d ",in[i]);
ans=max;
DFS(-1,0,0);
printf("%d\n",ans);
}
}
状态压缩DP
1 #include<stdio.h>
2 #include<string.h>
3 #define inf 999999
4 #define min(x,y) x<y?x:y
5 #define maxn 25
6 int dp[1<<16][20];//dp[s][j]表示到达 使得最后一个 图色的矩形是j,到达s状态所用的次数
7 int m[maxn];
8 struct node
9 {
10 int xl,yl,xr,yr,c;
11 }p[maxn];
12 int n;
13 bool check(int i,int j)
14 {
15 if(p[i].yr!=p[j].yl)return false;
16 if(p[i].xr<=p[j].xl)return false;
17 if(p[i].xl>=p[j].xr)return false;
18 return true;
19
20
21 }
22 void build()
23 {
24 int i,j;
25 memset(m,0,sizeof(m));
26 for(i=0;i<n;i++)
27 {
28 for(j=0;j<n;j++)
29 {
30 if(check(i,j))
31 m[j]|=(1<<i);//将在j上面的矩形标记
32 }
33 }
34 }
35 void get_dp()
36 {
37 int i,j,s;
38 int state=1<<n;
39 for(i=0;i<state;i++)
40 {
41 for(j=0;j<n;j++)
42 {
43 dp[i][j]=inf;
44 }
45 }
46
47 for(i=0;i<n;i++)
48 if(m[i]==0)dp[1<<i][i]=1;
49
50
51 for(s=0;s<state;s++)
52 {
53 for(i=0;i<n;i++)
54 {
55 if(s&(1<<i))continue;//已经图过色了
56 if((s&m[i])!=m[i])continue;//他的上面还没图完
57 for(j=0;j<n;j++)
58 {
59 if((s&(1<<j))==0)continue;//j还没图色
60 int t=dp[s][j];
61 int x=1<<i;
62 if(p[i].c!=p[j].c)t++;
63 dp[x+s][i]=min(dp[s+x][i],t);
64
65 }
66 }
67
68
69 }
70
71 int ans=inf;
72 for(j=0;j<n;j++)
73 {
74 ans=min(ans,dp[state-1][j]);
75
76 }
77 printf("%d\n",ans);
78 }
79 int main()
80 {
81 int t;
82 scanf("%d",&t);
83 while(t--)
84 {
85 scanf("%d",&n);
86 for(int i=0;i<n;i++)
87 {
88 scanf("%d%d%d%d%d",&p[i].yl,&p[i].xl,&p[i].yr,&p[i].xr,&p[i].c);
89 }
90 build();
91 get_dp();
92 }
93 }