uva 11205 - The broken pedometer

暴力枚举所有的子集列,比较在每种情况下每行是否唯一,我把每行数据当成2进制转化为10进制之后比较的。这里枚举子集是用的位向量法,产生的子集序列 子集大小变化是不规则的,但是一旦有小的子集可以区分所有行,子集大的情况就不用计算了,直接可以忽略。

 

 

#include<stdio.h>
#include<math.h>
#include<stdlib.h>

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;
}

 

你可能感兴趣的:(uva 11205 - The broken pedometer)