天天看點

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;

}