损坏的计步器
一个马拉松运动员使用的计步器出现了问题。计步器是由7个线段(即LED灯)组成的:
但是因为计步器因为某些原因损坏了,只有部分LED灯工作。运动员想知道下列的各个数字能否被正确识别:
比如,当正常工作的LED为:
数字2和数字3显示都如下:
所有它们不能被正确识别。但是当正常工作的LED灯为:
所有的数字显示如下:
它们可以全部被正确识别。
由于运动员在大学教授算法课程,他一边跑步一边思考,他相出了一个有关解决他的损坏的计数器的编程问题。问题包括求出能够正确识别每一个数字的最小LED数,给出LED的个数P,和所需要组成的数字个数N
输入:
输入的第一行由一个数字组成,代表案例数。每个案例包含多行,第一行为数字P,代表LED灯个数,第二行为数字N,代表需要辨别的的数字,接下来N行表示具体的数字。P的最大值是15,N的最大值是100.
输出:
每个答案占一行,代表最小LED数
样例输入:
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
样例输出:
5
4
分析:二进制法求集合
#include <iostream>
#include <stdio.h>
#include <string>
#include <map>
using namespace std;
const int maxn = 105;
const int inf = 0x3f3f3f3f;
int P, N, ans = inf;
int a[maxn][maxn];
map<string, bool> coll;
void output()
{
for (int i = 1; i <= N; ++i)
{
for (int j = 1; j <= P; ++j)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
}
int main()
{
// freopen("e:\\input.txt", "r", stdin);
int T;
scanf("%d", &T);
while (T--)
{
ans = inf;
scanf("%d %d", &P, &N);
int i, j;
for (i = 0; i < N; ++i)
for (j = 0; j < P; ++j)
{
scanf("%d", &a[i][j]);
}
int state;
for (state = 0; state < (1 << P); ++state)
{
coll.clear();
for (i = 0; i < N; ++i)
{
string str = "";
for (j = 0; j < P; ++j)
{
if (a[i][j] && ((1 << (P - j - 1)) & state))
str += "1";
else
str += "0";
}
if (coll[str])
{
break;
}
else
{
coll[str] = true;
}
}
if (i >= N)
{
int num = 0;
int tmp = state;
while (tmp)
{
if (tmp & 1)
++num;
tmp >>= 1;
}
ans = ans < num ? ans : num;
}
}
printf("%d\n", ans);
}
return 0;
}