UVA-11205 The Broken Pedometer 模拟 + 状态压缩

 The Broken Pedometer 

The Problem

A marathon runner uses a pedometer with which he is having problems. In the pedometer the symbols are represented by seven segments (or LEDs):

But the pedometer does not work properly (possibly the sweat affected the batteries) and only some of the LEDs are active. The runner wants to know if all the possible symbols:

can be correctly identified. For example, when the active LEDs are:

numbers 2 and 3 are seen as:

so they cannot be distinguished. But when the active LEDs are:

the numbers are seen as:

and all of them have a different representation.

Because the runner teaches algorithms at University, and he has some hours to think while he is running, he has thought up a programming problem which generalizes the problem of his sweat pedometer. The problem consists of obtaining the minimum number of active LEDs necessary to identify each one of the symbols, given a number P of LEDs, and N symbols to be represented with these LEDs (along with the codification of each symbol).

For example, in the previous sample P = 7 and N = 10. Supposing the LEDs are numbered as:

The codification of the symbols is: "0" = 1 1 1 0 1 1 1; "1" = 0 0 1 0 0 1 0; "2" = 1 0 1 1 1 0 1; "3" = 1 0 1 1 0 1 1; "4" = 0 1 1 1 0 1 0; "5" = 1 1 0 1 0 1 1; "6" = 1 1 0 1 1 1 1; "7" = 1 0 1 0 0 1 1; "8" = 1 1 1 1 1 1 1; "9" = 1 1 1 1 0 1 1. In this case, LEDs 5 and 6 can be suppressed without losing information, so the solution is 5.

The Input

The input file consists of a first line with the number of problems to solve. Each problem consists of a first line with the number of LEDs (P), a second line with the number of symbols (N), and N lines each one with the codification of a symbol. For each symbol, the codification is a succession of 0s and 1s, with a space between them. A 1 means the corresponding LED is part of the codification of the symbol. The maximum value of P is 15 and the maximum value of N is 100. All the symbols have different codifications.

The Output

The output will consist of a line for each problem, with the minimum number of active LEDs necessary to identify all the given symbols.

Sample Input

2
7
10
1 1 1 0 1 1 1
0 0 1 0 0 1 0
1 0 1 1 1 0 1
1 0 1 1 0 1 1
0 1 1 1 0 1 0
1 1 0 1 0 1 1
1 1 0 1 1 1 1
1 0 1 0 0 1 0
1 1 1 1 1 1 1
1 1 1 1 0 1 1
6
10
0 1 1 1 0 0
1 0 0 0 0 0
1 0 1 0 0 0
1 1 0 0 0 0
1 1 0 1 0 0
1 0 0 1 0 0
1 1 1 0 0 0
1 1 1 1 0 0
1 0 1 1 0 0
0 1 1 0 0 0

Sample Output

5
4

  给定一个包含几个显示效果的显示器,众所周知,通过不同的组合可以产生不同的信息,但是有时候如果信息有限的情况下是可以不需要那么多的显示器的,比如只要求通过显示器来区分两个信号,那么只需要找到两者显示不同的那个显示器,开启这一台显示器,其亮或者是不亮来表示这两个信号。两个信号可以很简单的处理,但是一旦信号较多,处理起来就很麻烦了,不管你有没有想出一个好方法,反正我是没有。由于给定的数据范围比较小,这里就可以有一个暴力的方法,那就是先假设只有一个显示器,将其安放在不同的位置,看是否有满足题义的,然后就是两个显示器...... 这样下去知道满足题义为止,最后输出最少显示器的个数。计算的次数 [ C( P, 1 ) + C( P, 2 ) + ... + C( P, P ) ] * N; 时间复杂度为O( ( P ^ 2 - 1 ) * N ),这是能够处理掉的。这里有一个重要的思想就是状态压缩,由于每一位上只有0,1两个值,所以可以用一个 int 数在表示这个状态,比如 0 0 1 0 1,就可以表示为 5,P ^ 2 - 1 就用 for( 1   -    2 ^ P - 1 ) 来替代,每次操作用 & 来计算,因为这样可以模拟亮灯的过程,满足题义的数字再计算出他的含 1 位的个数,再选取最小的数即可。

  代码如下:

 1 #include <cstring>
2 #include <cstdlib>
3 #include <cstdio>
4 #include <map>
5 using namespace std;
6
7 int rec[105];
8
9 int main()
10 {
11 int T;
12 scanf( "%d", &T );
13 while( T-- )
14 {
15 int P, N;
16 map<int,bool>mp;
17 memset( rec, 0, sizeof( rec ) );
18 scanf( "%d %d", &P, &N );
19 for( int i = 0; i < N; ++i )
20 {
21 for( int j = 0; j < P; ++j )
22 {
23 int c;
24 scanf( "%d", &c );
25 if( c )
26 rec[i] += ( c << j );
27 }
28 }
29 int bound = ( 1 << P ) - 1, flag, min = 20, bit;
30 for( int i = 0; i <= bound; ++i )
31 {
32 mp.clear();
33 for( int j = 0; j < N; ++j )
34 {
35 int t = i & rec[j];
36 if( mp.count( t ) )
37 {
38 break;
39 }
40 else
41 {
42 flag = j;
43 mp[t] = true;
44 }
45 }
46 if( flag == N - 1 )
47 {
48 bit = i;
49 int ans = 0;
50 while( bit > 0 )
51 {
52 if( bit & 1 )
53 ans++;
54 bit >>= 1;
55 }
56 min = min < ans ? min : ans;
57 }
58 }
59 printf( "%d\n", min );
60 }
61 return 0;
62 }

  

posted @ 2011-09-08 09:15  沐阳  阅读(913)  评论(0编辑  收藏  举报