poj 1636 Prison rearrangement

题目链接:http://poj.org/problem?id=1636

1)DFS+DP法

View Code
 1 #include <iostream>
2 #include <cstring>
3 #include <cstdio>
4 using namespace std;
5 const int MAX=210;
6 int map[MAX][MAX];
7 int vist[3][MAX];
8 int dp[MAX][MAX];
9 int asize,bsize;
10 int m,r;
11 void init()
12 {
13 memset(dp,0,sizeof(dp));
14 memset(vist,0,sizeof(vist));
15 memset(map,0,sizeof(map));
16 }
17 void input()
18 {
19 int i,x,y;
20 scanf("%d%d",&m,&r);
21 for (i=1;i<=r;i++)
22 {
23 scanf("%d%d",&x,&y);
24 map[x][y]=1;//这里要注意 必须要赋值成单向 因为两个监狱的编号是相同的
25 }
26 }
27 void DFS(int side,int id)
28 {
29 int i,j;
30 vist[side][id]=1;
31 if(side==0)
32 {
33 asize++;
34 for (i=1;i<=m;i++)
35 if(map[id][i]&&!vist[1][i]){
36 DFS(1,i);
37 }
38 }
39 else {
40 bsize++;
41 for (j=1;j<=m;j++)
42 if(map[j][id]&&!vist[0][j]){
43 DFS(0,j);
44 }
45 }
46 }
47 void Knapsack( )
48 {
49 int i,j;
50 dp[0][0]=1;
51 for (i=m/2;i>=asize;i--)
52 for (j=m/2;j>=bsize;j--)
53 {
54 dp[i][j]=(dp[i][j]||dp[i-asize][j-bsize]);
55 }
56 }
57 void outprint()
58 {
59 int i;
60 for (i=m/2;i>=0;i--)
61 {
62 if(dp[i][i]){printf("%d\n",i);break;}
63 }
64
65 }
66 int main()
67 {
68 int con,i;
69 scanf("%d",&con);
70 while (con--)
71 {
72 init();
73 input();
74 for (i=1;i<=m;i++)
75 if (!vist[0][i])
76 {
77 asize=0;
78 bsize=0;
79 DFS(0,i);
80 Knapsack();
81 }
82 for (i=1;i<=m;i++)
83 if (!vist[1][i])
84 {
85 asize=0;
86 bsize=0;
87 DFS(1,i);
88 Knapsack();
89 }
90
91 outprint();
92 }
93 return 0;
94 }

 2)传递闭包+dp 这里有几个细节要注意

View Code
  1 #include <iostream>
2 #include <cstring>
3 #include <cstdio>
4 using namespace std;
5 const int MAX=205;
6 int map[MAX*2][MAX*2];
7 int dp[MAX][MAX];
8 int groupa[MAX*2];
9 int groupb[MAX*2];
10 int vist[MAX*2];
11 int m,r;
12 int cnt;
13 void init()
14 {
15 memset(vist,0,sizeof(vist));
16 memset(map,0,sizeof(map));
17 memset(dp,0,sizeof(dp));
18 memset(groupa,0,sizeof(groupa));
19 memset(groupb,0,sizeof(groupb));
20 }
21
22 void input()
23 {
24 int i,x,y;
25 scanf("%d%d",&m,&r);
26 for (i=1;i<=2*m;i++)
27 {
28 map[i][i]=1;
29 }
30 for (i=1;i<=r;i++)
31 {
32 scanf("%d%d",&x,&y);
33 map[x][y+m]=map[y+m][x]=1;
34 }
35 }
36 void Floyd()
37 {
38 int i,j,k;
39 for (k=1;k<=2*m;k++)
40 for (i=1;i<=2*m;i++)
41 if(map[i][k])
42 {
43 for (j=1;j<=2*m;j++)
44 {
45 map[i][j]=map[i][j]||(map[i][k]&&map[k][j]);
46 }
47 }
48 }
49 void Build()
50 {
51 int i,j;
52 cnt=0;
53 for (i=1;i<=2*m;i++)
54 if(!vist[i])
55 {
56 cnt++;
57 for (j=1;j<=2*m;j++)
58 {
59 if(map[i][j])
60 {
61 if(j<=m)
62 {
63 groupa[cnt]++;
64
65 }
66 else groupb[cnt]++;
67 vist[j]=1;
68 }
69 }
70 }
71 }
72
73 void Knapsack()
74 {
75 int i,j,k;
76 dp[0][0]=1;
77 for(k=1;k<=cnt;k++)
78 for (i=m/2;i>=groupa[k];i--)
79 for (j=m/2;j>=groupb[k];j--)
80 {
81 dp[i][j]=dp[i][j]||dp[i-groupa[k]][j-groupb[k]];
82 }
83
84 }
85
86 void outprint()
87 {
88 int i;
89 for (i=m/2;i>=0;i--)
90 if(dp[i][i]){
91 printf("%d\n",i);
92 break;
93 }
94
95 }
96 int main()
97 {
98 int ca;
99 scanf("%d",&ca);
100 while (ca--)
101 {
102 init();
103 input();
104 Floyd();
105 Build();
106 Knapsack();
107 outprint();
108 }
109 return 0;
110 }

 

 

posted @ 2012-04-03 13:41  我们一直在努力  阅读(517)  评论(0编辑  收藏  举报