Uva1252 详解 20个问题 Twenty Questions

这题我参考了刘汝佳的代码:链接https://github.com/aoapc-book/aoapc-bac2nd/blob/master/ch9/UVa1252.cpp#L27我想来说下这题的结题思路,首先这个串最多11,几乎告诉你= =用状态压缩,用这个来存储状态,因为选择判断的列肯定不是连续的,状态压缩正好可以表示然后不好想的是再设一个状态来保存当前所有检查过的点哪些是1。这个用下面代码中的init()来预处理,cnt就是用来记录,在检查过这几个点后,满足这几个点条件的有几个。在这个cnt数组中一般情况大部分都是0,其次是1,因为基本上检查完几个后,就可以确定了,你就是要找出最优的解。刚开始没有用vis直接搜的发现不行,时间相当长,虽然下面的因为这样= =等于没有动态规划,但是弄完还是不行,发现样例都需要0.7s,然后看了题解发现还需要加一个if(cnt[s2][a2]>=1&&cnt[s2][a]>=1) 大部分的都是cnt都是0,没有必要继续搜。改完以后0.057了.int need = max(DP(s2, a2), DP(s2, a)) + 1;这个是max的原因是你猜的是后是猜0或者1,但是这不一定是最优的,所以取max。下面有min满足条件下的最优解。当递归到
#pragma warning(disable:4996)
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<algorithm>
#include<iostream>
#include<time.h>
#include<map> 
#include<set>
#include<sstream>
#include<functional>
#include<cassert>
#include<list>
#include<iterator>
#include<utility>
#include <stdexcept>  
#include <sstream>
#include <fstream> 
#include<unordered_map>
#include<unordered_set>
#include<ctype.h>
#include<queue>

using namespace std;
const int INF = 0x3f3f3f3f;
int m, n;
const int maxm = 11 + 5;
const int maxn = 128 + 5;
char str[maxn][maxm];
int cnt[1 <<11][1 <<11];
int dp[1 << 11][1 << 11];
int vis[1 << 11][1 << 11];
int kase;

void init()
{
	memset(cnt, 0, sizeof(cnt));
	for (int s = 0; s < (1 << m); s++)
	{
		for (int i = 0; i < n; i++)
		{
		    int feature = 0;
			for (int j = 0; j < m; j++)
			{
				if (str[i][j] == '1')
					feature += 1 << j;
			}
		    cnt[s][feature&s]++;
		}
	}
}

int DP(int s, int a)
{
	if (cnt[s][a] ==1)
		return 0;
	if (cnt[s][a] == 2)
		return 1;
	if (vis[s][a] == kase)
		return dp[s][a];
	vis[s][a] = kase;
	int& ans = dp[s][a];
	ans =m;
	for (int i = 0; i < m; i++)
	{
		if (!(s&(1 << i)))
		{
			int s2 = s | (1 << i);
			int a2 = a | (1 << i);
			if (cnt[s2][a] >= 1 && cnt[s2][a] >= 1)
			{
				int need = max(DP(s2, a2), DP(s2, a)) + 1;
				ans = min(need, ans);
			}
		}
	}
	return ans;
}

int main()
{
	kase = 0;
	while (cin >> m >> n,m||n)
	{
		kase++;
		for (int i = 0; i < n; i++)
			scanf("%s", str[i]);
		init();
		cout << DP(0, 0) << endl;
	}
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值