正如acb0y所说,很黄很暴力,学到了枚举子集 #include <iostream> #include <cstring> #include <cstdlib> using namespace std ; int ncase ; int p , n , c ; char data[101][16] ; bool vis[16] ; int a[40000][20] ; char tem[101][16] ; int ans ; void input() { cin >> p >> n ; memset( data , 0 , sizeof( data ) ) ; for( int i = 0 ; i < n ; ++i ) { for( int j = 0 ; j < p ; ++j ) cin >> data[i][j] ; data[i][p] = '/0' ; } return ; } void printsubset( int s , int p ) { for( int i = 0 ; i < p ; ++i ) if( s & ( 1 << i ) ) a[c][i] = 1 ; else a[c][i] = 0 ; c++ ; return ; } void subset( int p ) { for( int i = 0 ; i < ( 1 << p ) ; ++i ) { printsubset( i , p ) ; } return ; } int cmp( const void * _a , const void * _b ) { char * a = ( char * ) _a ; char * b = ( char * ) _b ; return strcmp( a , b ) ; } int find( int pos , int n , int p ) { int _ans = 0 ; //在a[pos]的掩码下看是否n个数还是能独立表示的,a[pos][i]为0时表示把它给掩盖了,所以全换成'0'或'1' for( int i = 0 ; i < p ; ++i ) { if( a[pos][i] ) _ans++ ; else for( int j = 0 ; j < n ; ++j ) tem[j][i] = '1' ; } qsort( tem , n , sizeof( tem[0] ) , cmp ) ; int flag = 1 ; for( int i = 0 ; i < n - 1 ; ++i ) { if( ! strcmp( tem[i] , tem[i+1] ) ) { flag = 0 ; break ; } } if( flag ) return _ans ; else return 16 ; } void solve() { ans = p ; c = 0 ; subset( p ) ;//找到所有子集 for( int i = 0 ; i < c ; ++i ) { memcpy( tem , data , sizeof( data ) ) ;//不能改变data因为每次都有用到 int t = find( i , n , p ) ; if( t < ans )//更新 ans = t ; } return ; } void output() { cout << ans << endl ; return ; } int main() { cin >> ncase ; while( ncase-- ) { input() ; solve() ; output() ; } return 0 ; }