1. 程式人生 > >POJ 1632 Vase collection【狀態壓縮+搜索】

POJ 1632 Vase collection【狀態壓縮+搜索】

possible span pro there ini -- cal collector 找到

題目傳送門: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

Northwestern Europe 2003

題意概括:

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

POJ 1632 Vase collection【狀態壓縮+搜索】