POJ 1632 Vase collection【状态压缩+搜索】

题目传送门:http://poj.org/problem?id=1632

Vase collection

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 2308   Accepted: 901

Description

Mr Cheng is a collector of old Chinese porcelain, more specifically late 15th century Feng dynasty vases. The art of vase-making at this time followed very strict artistic rules. There was a limited number of accepted styles, each defined by its shape and decoration. More specifically, there were 36 vase shapes and 36 different patterns of decoration - in all 1296 different styles. 
For a collector, the obvious goal is to own a sample of each of the 1296 styles. Mr Cheng however,like so many other collectors, could never afford a complete collection, and instead concentrates on some shapes and some decorations. As symmetry between shape and decoration was one of the main aestheathical paradigms of the Feng dynasty, Mr Cheng wants to have a full collection of all combinations of k shapes and k decorations, for as large a k as possible. However, he has discovered that determining this k for a given collection is not always trivial. This means that his collection might actually be better than he thinks. Can you help him?

Input

On the first line of the input, there is a single positive integer n, telling the number of test scenarios to follow. Each test scenario begins with a line containing a single positive integer m <= 100, the number of vases in the collection. Then follow m lines, one per vase, each with a pair of numbers, si and di, separated by a single space, where si ( 0 < si <= 36 ) indicates the shape of Mr Cheng's i:th vase, and di ( 0 < di <= 36 ) indicates its decoration.

Output

For each test scenario, output one line containing the maximum k, such that there are k shapes and k decorations for which Mr Cheng's collection contains all k*k combined styles.

Sample Input

2
5
11 13
23 5
17 36
11 5
23 13
2
23 15
15 23

Sample Output

2
1

Source

 

题意概括:

N个瓶子,每个瓶子有两种属性 形状 和 颜色,我们要找到最大 K, 使得K*K个瓶子 都是由 K种 形状和颜色组成。

不是很好理解...

另一种理解可以把shape和decoration看成点,它们之际的对应关系看成边,这样就得到两个集合的映射。用A表示shape的集合,B表示decoration的集合。题目要求的就是原图的一个最大子图:使得该子图也可以分为A的子集A’和B的子集B’两部分,且从A’的每个点出发,到B’的任意点都存在边。

参考:https://blog.csdn.net/sj13051180/article/details/6612732

解题思路:

呃...我觉得这道题最大的难点在于理解题意了,看题目看到怀疑人生。

题意搞懂之后很容易想到状态压缩,之前搞状态压缩都在DP上搞,这次搬到搜索上有意思。

我们不妨设一个数组 Cp[ x ] = y; x(数组下标)表示shape, 数值 y 表示decoratio;y 最大可以到达 2^36, 所以数组定义个 long long 即可。 (有点像浓缩版的vector)

接下来就是暴力深搜去匹配了,两两匹配,如果匹配成功则两个合并后继续匹配(试试能否继续壮大),如果匹配失败则分道扬镳(各自寻找属于自己的那群小伙伴),不断匹配去寻找K的最大值。

 

AC code(116k 0ms):

 1 //DFS 状态压缩
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <iostream>
 6 #include <algorithm>
 7 #define ll long long int
 8 using namespace std;
 9 
10 const int MAXN = 50;
11 ll Cp[MAXN];
12 int N, ans;
13 
14 int cmp(ll num)
15 {
16     int cnt = 0;
17     while(num)
18     {
19         cnt+=(num&1);
20         num>>=1;
21     }
22     return cnt;
23 }
24 void dfs(int k, int st, ll tp)  ///花瓶数 当前花瓶编号 当前累积的颜色值
25 {
26     if(k > ans) ans = k;
27     for(int i = st; i <= 36; i++)
28     {
29         if(cmp(Cp[i]&tp) > k)
30             dfs(k+1, i+1, (Cp[i]&tp));
31     }
32 }
33 int main()
34 {
35     int T, u, v;
36     scanf("%d", &T);
37     while(T--)
38     {
39         memset(Cp, 0, sizeof(Cp));
40         ans = 0;
41         scanf("%d", &N);
42         for(int i = 0; i < N; i++)
43         {
44             scanf("%d%d", &u, &v);
45             Cp[u]|=(1ll<<v);
46         }
47         dfs(0, 1, (1ll>>36)-1);
48         printf("%d\n", ans);
49     }
50     return 0;
51 }
View Code

 

posted @ 2018-08-19 03:44  莜莫  阅读(174)  评论(0编辑  收藏  举报