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):

p11205a.gif

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:

p11205b.gif

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

p11205c.gif

numbers 2 and 3 are seen as:

p11205d.gif

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

p11205e.gif

the numbers are seen as:

p11205f.gif

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:

p11205g.gif

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 }

  

转载于:https://www.cnblogs.com/Lyush/archive/2011/09/08/2170566.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值