【题解】UVA1252 Twenty Questions

题意

n 个物品,每个物品有 m 个特征,每次询问一个特征,求最少多少次能确定所求物品。

Solution:

考点:状压 dp 。

首先不能暴力枚举,这样第二个样例输出 5。但是它启发我们当某一组特征 cnt[S]=1 时答案是唯一的。 因为决策是变化的,所以考虑设 dp[S][T] 表示当前问了集合 S 的特征,其中集合 T 的答案是 1 的最小询问数。显然当 cnt[S][T]=1 时返回 0cnt[S][T]=0 是不合法状态。

时间复杂度 O(m3^m+n2^m)

思考:询问顺序是否对答案有影响?

显然是有影响的,因为这个过程不可逆。

输入的时候按十进制输了,导致自闭了一下午。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
int n,m,cnt[1<<11][1<<11],dp[1<<11][1<<11],a[1<<11];
string s;
vector<int> vec[15];
map<int,bool> mp;
int dfs(int x,int y) {
	if(cnt[x][y] <= 1) return 0;
	if(~dp[x][y]) return dp[x][y];
	int res = 20;
	for(int i=0;i<m;i++) {
		if((x>>i) & 1) continue;
		res = min(res, max(dfs(x | (1<<i), y), dfs(x | (1<<i), y | (1<<i))) + 1);
	}
	return dp[x][y] = res;
}
int main() {
	while(scanf("%d%d",&m,&n) && (n || m)) {
		for(int i=0;i<(1<<m);i++) {
			for(int j=i;j;j=(j-1)&i) {
				cnt[i][j] = 0;
				dp[i][j] = -1;
			}
			dp[i][0] = -1;
			cnt[i][0] = 0;
		}
		for(int i=1;i<=n;i++) {
			cin>>s; a[i]=0; 
			for(int j=0;j<m;j++) {
			    if(s[j] == '1') a[i] |= 1<<j;
			}
			for(int j=0;j<(1<<m);j++) {
				cnt[j][a[i] & j] ++;
			}
		} 
		printf("%d\n",dfs(0,0));
	}
} 
上一篇:DISPLAY


下一篇:java中json转map