暴力枚举所有的子集列,比较在每种情况下每行是否唯一,我把每行数据当成2进制转化为10进制之后比较的。这里枚举子集是用的位向量法,产生的子集序列 子集大小变化是不规则的,但是一旦有小的子集可以区分所有行,子集大的情况就不用计算了,直接可以忽略。
#include#include #include int led[105][20];int flag[20];int p, n;int minNum;void judge() { int arr[105]; int idx = 0; int setSize = 0; int i, j; for (i = 0; i < p; i++) { if (flag[i]) { setSize++; } } /*子集列超过当前最小值,直接忽略*/ if (setSize >= minNum) return; /*每一行2进制数据根据子集列转化成十进制,如果有相同的则失败返回。*/ for (i = 0; i < n; i++) { int curNum = 0; for (j = 0; j < p; j++) { if (flag[j] && led[i][j]) { curNum += pow(2, j); } } for (j = 0; j < idx; j++) { if (arr[j] == curNum) { return; } } arr[idx++] = curNum; } /*没有返回表明没有相同的行*/ if (setSize < minNum) minNum = setSize; return;}/*递归生成子集列,在子集列中判断*/void subSet(int cur) { if (cur == p) { judge(); return; } flag[cur] = 0; subSet(cur + 1); flag[cur] = 1; subSet(cur + 1);}int findMinNum() { minNum = p; subSet(0); return minNum;}int main() { int cases; scanf("%d", &cases); while (cases--) { scanf("%d%d", &p, &n); int i, j; for (i = 0; i < n; i++) for (j = 0; j < p; j++) scanf("%d", &led[i][j]); printf("%d\n", findMinNum()); } return 0;}