天天看点

UVA 记忆化搜索状压dp 1252

记忆化 搜索,题目要求求要猜出每个物体所需要的最小次数

开始理解错题意了,弄成一次性猜出所有的物体

其实是求猜出每个物体的次数中的最大次数

//dp[s][b]

//s : 代表此时询问过的集合

//b : 代表此时所要猜到的物体w,在集合s中所具有的特征

#include <cstdio>

#include <cstdlib>

#include <iostream>

#include <algorithm>

#include <cstring>

#include <climits>

#include <string>

#include <vector>

#include <cmath>

#include <stack>

#include <queue>

#include <set>

#include <map>

#include <sstream>

#include <cctype>

using namespace std;

typedef long long ll;

typedef pair<int ,int> pii;

#define MEM(a,b) memset(a,b,sizeof a)

#define CLR(a) memset(a,0,sizeof a);

const int inf = 0x3f3f3f3f;

const int MOD = 1e9 + 7;

//#define LOCAL

int n,m;

char ch[150][15];

int dp[(1<<12)][(1<<12)];

int a[(1<<12)];

int dfs(int s,int b){

if(dp[s][b]!=inf)return dp[s][b];

int cnt = 0;

for(int i=1;i<=m;i++){

if((a[i]&s) == b)cnt++;

// 如果只有小于一个物体满足此时的特征

}

if(cnt<=1)return dp[s][b]=0;

for(int i=0;i<n;i++){

if(s & (1<<i))continue;

dp[s][b]=min(dp[s][b],max(dfs(s | (1<<i),b),dfs(s | (1<<i),b | (1<<i)))+1);

}

return dp[s][b];

}

int main()

{

#ifdef LOCAL

freopen("in.txt", "r", stdin);

// freopen("out.txt","w",stdout);

#endif

while(cin >> n >> m && (n+m)){

MEM(dp,inf);

CLR(a);

for(int i=1;i<=m;i++)cin >> ch[i];

for(int i=1;i<=m;i++){

for(int j=0;j<n;j++){

a[i] |= (1<<j)*(ch[i][j]-'0');//预处理每个物体的状态

}

}

cout <<  dfs(0,0) << endl;

}

return 0;

}