您的位置:首页 > 产品设计 > UI/UE

状压DP+记忆化搜索 UVA 1252 Twenty Questions

2015-08-15 15:55 519 查看
题目传送门

 /*
题意:给出一系列的01字符串,问最少要问几个问题(列)能把它们区分出来
状态DP+记忆化搜索:dp[s1][s2]表示问题集合为s1。答案对错集合为s2时,还要问几次才能区分出来
若和答案(自己拟定)相差小于等于1时,证说明已经能区分了,回溯。否则还要加问题再询问
*/
/************************************************
* Author        :Running_Time
* Created Time  :2015-8-13 10:54:26
* File Name     :UVA_1252.cpp
************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int MAXN = 128 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int dp[(1<<11)+10][(1<<11)+10];
int p[MAXN];
char str[13];
int m, n;

int DFS(int s1, int s2) {
if (dp[s1][s2] != INF)  return dp[s1][s2];
int cnt = 0;
for (int i=1; i<=n; ++i)    {
if ((p[i] & s1) == s2)  cnt++;
}
if (cnt <= 1)   {
return dp[s1][s2] = 0;
}
for (int i=0; i<m; ++i) {
if (s1 & (1 << i))  continue;
int nex = s1 | (1 << i);
dp[s1][s2] = min (dp[s1][s2], max (DFS (nex, s2), DFS (nex, s2 ^ (1 << i))) + 1);
}

return dp[s1][s2];
}

int main(void)  {       //UVA 1252 Twenty Questions
while (scanf ("%d%d", &m, &n) == 2) {
if (!m && !n)   break;
for (int i=1; i<=n; ++i)    {
scanf ("%s", str);  p[i] = 0;
for (int j=0; j<m; ++j)  {
if (str[j] == '1')  {
p[i] |= (1 << j);
}
}
}
memset (dp, INF, sizeof (dp));
printf ("%d\n", DFS (0, 0));
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: