ZOJ3305Get Sauce 状压DP,

6 篇文章 0 订阅

状压DP的题目留个纪念,首先题意一开始读错了,搞了好久,然后弄好了,觉得DFS可以,最后超时,修改了很久还是超时,没办法看了一下n的范围,然后觉得状压可以,但是没有直接推出来,就记忆化搜索了一下,可是一直错,莫名奇妙,然后没办法看了一下题解,发现了下面这个比较好的方法,然后按照这个方程去推,然后敲,也是WA了好多把,写的太搓了,没人家的清楚明了,唉~也算是给自己留个纪念,状压一直做的都不太好~唉~还好理解了,

参考了  http://blog.csdn.net/nash142857/article/details/7968554
还有http://linest.iteye.com/blog/1175648
这两篇一起看了 了解了,也知道自己记忆化搜索错在哪里了,改了也A掉了


int n,m;

int dp[(1<<16) + 1];

void init() {
	memset(dp,-1,sizeof(dp));
}

bool input() {
	while(cin>>n>>m) {
		return false;
	}
	return true;
}

void cal() {
	int k;
	int q = m;
	int ss = (1<<n) - 1;
	while(q--) {
		int k;
		scanf("%d",&k);
		int s = 0;
		for(int i=0;i<k;i++) {
			int x;
			scanf("%d",&x);
			s |= (1<<(x - 1));
		}
		int now = ss^s;//并集减去交集,其实以1<<16为全集的,所以相当于补集
		dp[s] = max(dp[s],1);//加边界
		for(int i=now;i != 0;i = (i - 1)&now) {//对于补集进行枚举,然后跟原来的集合取交集
			if(dp[i] != -1)
				dp[s|i] = max(dp[s|i],dp[i] + 1);
		}
	}
	int ans = -1;
	for(int i=0;i<(1<<n);i++)
		ans = max(dp[i],ans);
	if(ans == -1)ans = 0;
	cout<<ans<<endl;
}

void output() {

}

int main() {
	while(true) {
		init();
		if(input())return 0;
		cal();
		output();
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值