UVa 11205 - The broken pedometer

求可区分出所有行的最小列数,用位向量法生成子集,然后枚举最小子集。最需要注意的是其0与1之间可能不止一个空格,开始用char型数组 scanf("%c%c", &a[i][j], &c); 读取的,因为这个WA了好几次,如果直接用int型数组求则可以省去很多麻烦。

代码如下:

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cctype>
#include <cmath>
using namespace std;

char b[101][17];
int a[101][17], flag[17], _min;

int subset(int n, int p, int cur)
{
    if(cur == p)
    {
        int ct = 0;
        for(int i = 0; i < p; i++)
            if(flag[i])
            {
                for(int j = 0; j < n; j++)
                    b[j][ct] = a[j][i] + '0';
                ++ct;
            }
        for(int i = 0; i < n; i++)
            b[i][ct] = 0;
        for(int i = 0; i < n - 1; i++)
            for(int j = i + 1; j < n; j++) // 所有子集应都不相同才可区分
                if(!strcmp(b[i], b[j]))
                    return 0;
        if(_min > ct)
            _min = ct;
        return 1;
    }
    flag[cur] = 0;
    subset(n, p, cur + 1);
    flag[cur] = 1;
    subset(n, p, cur + 1);
    return 0;
}
int main()
{
#ifdef test
    freopen("in.txt", "r", stdin);
#endif
    int t, p, n, ct;
    scanf("%d", &t);
    while(t--)
    {
        memset(flag, 0, sizeof(flag));
        scanf("%d%d", &p, &n);
        getchar();
        for(int i = 0; i < n; i++)
            for(int j = 0; j < p; j++)
                scanf("%d", &a[i][j]);
        _min = p;
        ct = subset(n, p, 0);
        printf("%d\n", _min);
    }
    return 0;
}


你可能感兴趣的:(c)