CodeChef Mike and Stamps

本文探讨了一种解决复杂状态问题的算法,通过状态压缩和互斥判断优化了内存使用,提高了效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写了我1小时,看到m<=20就知道状态压缩,开始的时候想岔了,dp[1<<20][20000] 超内存,用map<int,int> dp[1<<20] 写。花了半小时还错的。

灵光一闪,有共同的不就是互斥嘛!先两两判互斥,再状态压缩判是否状态互斥。状态位的个数就是答案。

#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;

const int MAX=1<<20;
int mp[21][20001],n,m;
int a[21][21],num[MAX],dp[MAX];
void init(){
	num[0]=0;
	for(int i=1;i<MAX;i++)
		num[i]=num[i-(i&-i)]+1;
}
int ok(int state){//判断该状态是否能存在
	int last=state&-state,t;
	if(dp[state-last]==0) return 0;
	last=-1,t=0;
	while(state){
		if(state&1){
			if(last==-1)
				last=t;
			else{
				if(a[t][last]==1)
					return 0;
			}
		}
		t++;
		state>>=1;
	}
	return 1;
}
int main(){
	int k,t;
	init();
	while(cin>>n>>m){
		memset(mp,0,sizeof mp);
		for(int i=0;i<m;i++){
			scanf("%d",&k);
			for(int j=0;j<k;j++)
				scanf("%d",&t),mp[i][t]=1;
		}
		memset(a,0,sizeof a);
		for(int i=0;i<m;i++){//O(m*m*n) 0.1s 
			for(int j=i+1;j<m;j++)
				for(int k=1;k<=n;k++)
					if(mp[i][k]&&mp[j][k]){//i与j是否互斥
						a[j][i]=a[i][j]=1;break;
					}
		}
		memset(dp,0,sizeof dp);
		int mx=1<<m,ans=0;
		dp[0]=1;
		for(int s=1;s<mx;s++){//该状态是否能存在
			if(ok(s)){
				dp[s]=1;
				ans=max(ans,num[s]);
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值